Java provides a lot of useful tool classes for development, which can help us to write concurrent programs more efficiently, and we'll cover the use of these utilities in this article.
ThreadLocal
The Threadlocal class is used to solve the problem of sharing a variable in multi-threaded, when multiple threads access the same variable can result in errors, prevent this error the first way is to use locks to protect the object, the second method is to completely eradicate the share, that is, each thread accesses its own private variables. Some students will feel that the second method will have some limitations, because sometimes you have to share the same variable. Yes, there are limitations, but in many cases the same effect can be achieved without sharing variables, and threadlocal is designed to solve this problem.
Threadlocal use the following methods:
classIncreasethreadImplementsRunnable { Public voidrun () { for(inti=0; i< 10000; i++) {TLTest.number.set (TLTest.number.get ()+ 1); } //The following is a summary code synchronized(tltest.result) {Tltest.result+=TLTest.number.get (); } }} Public classTltest { Public StaticThreadlocal<integer>Number ; Public StaticInteger result = 0; Public Static voidMain (string[] args)throwsException { number=NewThreadlocal<integer>() { PublicInteger InitialValue () {return0; } }; Executorservice exec=Executors.newcachedthreadpool (); Exec.execute (NewIncreasethread ()); Exec.execute (NewIncreasethread ()); Exec.shutdown (); Thread.Sleep (500); System.out.println ("Result:" +result); }}
The output results are as follows:
result:20000
In the Tltest class we define the threadlocal variable and the integer variable, and the threadlocal variable needs to create an anonymous inner class for it to specify the initial value, and we specify the initial value as 0. We define a thread class, which is responsible for adding the value of threadlocal to 10000, and the last thread summarizes its results into the tltest.result variable. In this process, although the two threads we created operate on the same threadlocal variable, there is no error in the result of the calculation. Because threadlocal allocates different storage space for each thread, we can simply interpret it as a thread object and a value of map<thread,integer> (note: It's understandable, but actually not).
Countdownlatch
Countdownlatch is used for inter-threading collaboration, and its use is similar to wait ()/notify (), Countdownlatch class has two methods: Countdown () and await () methods, The number of times the countdown () method call is specified for the Countdownlatch object when it is created, and when the await () method is called, the thread is blocked until the countdown () method is called for the specified number of times. Imagine a situation in which a foreman distributes a task to a different worker when he receives the task, and only when all the workers have finished their work will the foreman be able to complete the job.
We use code to simulate this situation:
classWorkerImplementsRunnable {Private intID; PublicWorker (intID) { This. ID =ID; } Public voidrun () {Random rand=NewRandom (); intWorktime = Rand.nextint (1000); System.out.println (ID+ ": Start working"); Try{Thread.Sleep (worktime);}Catch(Exception e) {} System.out.println (ID+ ": Completed"); CDLTest.cdl.countDown (); }} Public classCdltest {Private Static intNumberofworker = 3; Public StaticCountdownlatch CDL =NewCountdownlatch (Numberofworker); Public Static voidMain (string[] args)throwsException {executorservice exec=Executors.newcachedthreadpool (); for(inti=0; i<numberofworker; i++) {Exec.execute (NewWorker (i)); } exec.shutdown (); Cdl.await (); System.out.println ("Foreman: Completion"); }}
The output results are as follows:
1: Start working
2: Start working
0: Start working
1: Completed
2: Completed
0: Completed
Foreman: Completion
In this example, the main thread assumes the role of the foreman and calls the await () method to wait for the worker thread to complete the work. We also created 3 worker threads through the thread pool, and we used random numbers to get each thread to sleep at random for 0-1000 milliseconds to simulate worker work.
Each worker calls the countdown () method after completing his or her task, and when all the worker threads have finished their work, the main thread can "finish the job".
Priorityblockingqueue
Priorityblockingqueue and Linkedblockingqueue, arrayblockingqueue similar to the previous, they all realized the Blockingqueue interface, But the biggest difference between priorityblockingqueue and them is that the queue takes the highest priority, not the first entry, each time it is taken out. Therefore, in order to achieve its priority characteristics, the elements in the container must implement the comparable interface, otherwise the container will throw classcastexception exception. Priorityblockingqueue is also thread-safe, so use it without locking. Since we have tested Linkedblockingqueue's blocking, we have not tested the Priorityblockingqueue, simply test its "priority" nature:
Public classPbqtest { Public Static voidMain (string[] args)throwsinterruptedexception {blockingqueue<String> PBQ =NewPriorityblockingqueue<string>(); String[] STRs=Newstring[]{"C", "A", "B"}; for(intI=0;i <strs.length;i++) {Pbq.add (strs[i]); } while(!Pbq.isempty ()) {System.out.println (Pbq.take ()); } }}
The output results are as follows:
A
B
C
The string class implements the comparable interface to compare the size of a string in alphabetical order. The order in which we add elements to the queue is "C", "A", "B", and the Order of removal is "a", "B", "C", which can be seen by the nature of its "precedence".
Summarize
This article introduces three commonly used tool classes, threadlocal is used to solve the problem of multi-threaded sharing the same variable, it is equivalent to creating a thread object as a key to the target object as a value of a map, but actually and map is different, For example, a map object does not garbage-reclaims the corresponding value after a thread exits, and threadlocal recycles it. Countdownlatch is used to synchronize multiple tasks, allowing certain tasks to wait for a set of operations performed by other tasks, noting that multiple threads can invoke the await () method, and all calls to await () when the number of calls to Countdown () reaches the specified number The thread of the method changes from the blocking state to the running state. The usage of priorityblockingqueue is similar to that of other implementations of the Blockingqueue interface, except that the order in which the elements in the priorityblockingqueue is fetched is sorted by priority.
Public number: Today said yards. Follow my public number to see the serial article. If you do not understand the problem, directly in the public message can be.
Java concurrency Programming (11) Common tools