1. Introduction of Countdownlatch
Countdownlatch is a synchronization tool that is primarily used to perform collaboration between threads. The Countdownlatch function is similar to the Thread.Join () method, allowing some threads to block until other threads have completed a series of operations before they are awakened. We can use Thread.Join () at the time of creating threads directly (before Java 5.0). After the thread pool appears, you must use Countdownlatch because the threads in the thread pool are not directly referenced.
Countdownlatch has two main methods, which are blocked when one or more threads call the await method. Other threads calling the countdown method will reduce the counter by 1, and when the value of the counter becomes 0 o'clock, the thread that is blocked by the await method is awakened and continues execution.
Implementation principle: The value of the counter is passed in by the constructor, and it initializes the state value of the AQS. When the thread calls the await method, it checks whether the value of state is 0, if it is returned directly (that is, does not block), if not, the thread that represents the node into row, and then blocks itself. When other threads call the countdown method, the counter is reduced by 1, and then the value of the counter is determined to be 0, and when it is 0 o'clock, the first node in the queue is awakened, because Countdownlatch uses the Aqs sharing mode, so the first node wakes up and wakes up the second node. And so on, all threads that are blocked by the await method can be awakened and continue to execute.
From the source code and the implementation principle can be seen a Countdownlatch object, can only be used once, can not be reused.
Await method source code
Public voidAwait ()throwsinterruptedexception {sync.acquiresharedinterruptibly (1);} Public Final voidAcquiresharedinterruptibly (intArgthrowsinterruptedexception {if(Thread.interrupted ())Throw NewInterruptedexception ();if(Tryacquireshared (ARG) < 0) doacquiresharedinterruptibly (ARG);}protected intTryacquireshared (intAcquires) {return(getState () = = 0)? 1:-1;}
Doacquiresharedinterruptibly mainly implements into row and blocking of threads.
Countdown method
Public voidCountdown () {sync.releaseshared (1);} Public Final BooleanReleaseshared (intARG) {if(Tryreleaseshared (ARG)) {doreleaseshared ();return true; }return false;}protected BooleanTryreleaseshared (intReleases) {//decrement count; signal when transition to zero for(;;) {intc = GetState ();if(c = = 0)return false;intNEXTC = c-1;if(Compareandsetstate (c, NEXTC))returnNEXTC = = 0; }}
Doreleaseshared Main implementation Wake the first node, the first node will wake up the second node, ....
2. Using the example
Packagejavalearning;ImportJava.util.Random;ImportJava.util.concurrent.CountDownLatch;ImportJava.util.concurrent.ExecutorService;ImportJava.util.concurrent.Executors; Public classCountdownlatchdemo {PrivateCountdownlatch CDL =NewCountdownlatch (2);PrivateRandom rnd =NewRandom ();classFirsttaskImplementsrunnable{PrivateString ID; PublicFirsttask (String ID) { This. id = ID;} @Override Public voidRun () {System.out.println ("Thread"+ ID +"is start");Try{Thread.Sleep (Rnd.nextint (1000));}Catch(Interruptedexception e) {E.printstacktrace ();} System.out.println ("Thread"+ ID +" is Over"); Cdl.countdown ();}}classSecondtaskImplementsrunnable{PrivateString ID; PublicSecondtask (String ID) { This. id = ID;} @Override Public voidRun () {Try{cdl.await ();}Catch(Interruptedexception e) {E.printstacktrace ();} System.out.println ("----------Thread"+ ID +"is start");Try{Thread.Sleep (Rnd.nextint (1000));}Catch(Interruptedexception e) {E.printstacktrace ();} System.out.println ("----------Thread"+ ID +" is Over");}} Public Static voidMain (string[] args) {Executorservice es = Executors.newcachedthreadpool (); Countdownlatchdemo CDLD =NewCountdownlatchdemo (); Es.submit (CDLD.NewSecondtask ("C")); Es.submit (CDLD.NewSecondtask ("D")); Es.submit (CDLD.NewFirsttask ("a")); Es.submit (CDLD.NewFirsttask ("b")); Es.shutdown ();}}
In this example, we created four threads A, B, C, D, and these four threads were submitted to the thread pool almost at the same time. The C thread and the D thread start executing after the A thread and the B thread are finished.
Run results
Thread A is start
Thread B is start
Thread B is over
Thread A is over
----------Thread C is start
----------Thread D is start
----------Thread D is over
----------Thread c is over3. Content reference [1] http://developer.51cto.com/art/201403/432095.htm
How Countdownlatch works and uses examples in Java and contract