Brief introduction:
Countdownlatch is a very practical multi-line programming tool class, usually used to control thread waiting, it can let a thread wait until the end of the countdown
Countdownlatch provides two main methods, await (), Countdown ().
Await: Causes the current thread to block, waiting for the counter to be 0
Countdown: The counter is minus one, the count is zero, and all the waiting threads are released
Instance:
Public classCountdownlatchdemoImplementsRunnable {Static FinalCountdownlatch end =NewCountdownlatch (10); Static FinalCountdownlatchdemo demo =NewCountdownlatchdemo (); @Override Public voidrun () {Try{Thread.Sleep (NewRandom (). Nextint (10) * 1000); System.out.println ("Check Complete ..."); End.countdown (); } Catch(interruptedexception e) {e.printstacktrace (); } } Public Static voidMain (string[] args)throwsinterruptedexception {executorservice exec= Executors.newfixedthreadpool (10); for(inti = 0;i < 10;i++) {Exec.submit (demo); } end.await (); System.out.println ("Fire!"); Exec.shutdown (); }}
Principle Analysis:
The count of Countdownlatch is implemented by a shared variable (volatile), which analyzes its three core functions: constructor, Countdownlatch (int count), blocking thread, await (), counter minus one, Countdown ().
Countdownlatch (int count)
Public Countdownlatch (int count) { ifthrownew illegalargumentexception ( "Count < 0"); This New Sync (count);}
Where sync is the inner class of Countdownlatch, and sync inherits the Abstractqueuedsynchronizer
Private Static Final classSyncextendsAbstractqueuedsynchronizer {Private Static Final LongSerialversionuid = 4982264981922014374L; Sync (intcount) {setState (count); } intGetCount () {returngetState (); } protected intTryacquireshared (intacquires) { return(getState () = = 0)? 1:-1; } 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; } }}
View Code
Where setState is setting the state variable in Abstractqueuedsynchronizer, which declares volatile.
State is the counter in Countdownlatch.
Await ()
Public voidAwait ()throwsinterruptedexception {sync.acquiresharedinterruptibly (1);} Public Final BooleanTryacquiresharednanos (intArgLongnanostimeout)throwsinterruptedexception {if(thread.interrupted ())Throw Newinterruptedexception (); returnTryacquireshared (ARG) >= 0 | |Doacquiresharednanos (ARG, nanostimeout);}
The function of acquiresharedinterruptibly () is to acquire a shared lock, and if the current thread is in a break state, throw interruptedexception, otherwise, call tryacquireshared (ARG) to attempt to acquire a shared lock. If the lock counter = 0, the lock is a fetch state, returns 1, otherwise, the lock is not available, then returns-1.
Doacquiresharednanos () causes the current thread to wait until the current thread acquires a shared lock (or the thread is interrupted) to return.
Countdown ()
Public void countdown () { sync.releaseshared (1);} Public Final boolean releaseshared (int arg) { if (tryreleaseshared (ARG)) { Doreleaseshared (); return true ; } return false ;}
The releaseshared () purpose is to have the current thread release the shared lock it holds.
The function of tryreleaseshared () is to release the shared lock and reduce the value of the lock counter by one.
Summarize
The Countdownlatch is implemented through shared locks. The Countdownlatch constructor passes the int parameter, which is the initial state of the counter, which indicates that a shared lock can be obtained at the same time by count threads.
When a thread calls the await method of Countdownlatch, the thread waits for the shared lock to be available (the counter is 0 o'clock) to acquire the shared lock and continue execution.
Each time the countdown is executed, the counter is reduced by one.
Resources
Java Multithreading Series--"Juc lock" 09 Countdownlatch Principle and Example
Java Multithreading Series--Counter Countdownlatch