Main methods :
Constructor CountDownLatch (int n)
blocking method latch.await () blocks the current thread until the latch status is completed
count by one latch.countDown () is decremented by 1 until the state change 0
For example scenario :
1. The long-distance race, running a total of two people together, everyone's ready to wait in place, the Starter ready to see every record once, not ready to reduce the number 1, until the number is ready to issuing the order starting from 0
public static void main(String[] args) throws InterruptedException { final CountDownLatch latch = new CountDownLatch(2); new Thread(()->{ try { System.out.println ( "standing ready to wait" + Thread.currentThread () getName ().); latch.await(); System.out.println ( "heard issuing the order to start the race" + Thread.currentThread () getName ().); } catch (InterruptedException e) { e.printStackTrace (); } }, "t1").start(); // Record number minus one is not prepared Thread.sleep (1000 ); latch.countDown(); new Thread(()->{ try { System.out.println ( "standing ready to wait" + Thread.currentThread () getName ().); latch.await(); System.out.println ( "heard issuing the order to start the race" + Thread.currentThread () getName ().); } catch (InterruptedException e) { e.printStackTrace (); } }, "t2").start(); // Record number minus one is not prepared Thread.sleep (1000 ); latch.countDown(); }
The results:
for the first time
Ready place waiting t1
Ready t2 still waiting
to hear issuing the order to start the race t1
heard issuing the order to start the race t2
the second time
Ready place waiting t1
Ready t2 still waiting
to hear issuing the order to start the race t2
heard issuing the order to start the race t1
Second latch.countDown that everything is ready (when), then start issuing the order, then began to start two players, who should finish are determined by their ability
Summary: racing use software commonly used in pressure measurement, while the number of open test thread, and enters a wait state, when all the threads ready, while performing business, to achieve high concurrency testing
2. The same is the long-distance race, since there are also naturally ranking tournament, only one player to finish in the final end of the game announced
public static void main(String[] args) throws InterruptedException { final CountDownLatch latch = new CountDownLatch(2); new Thread(()->{ try { System.out.println ( "trying to run" + Thread.currentThread () getName ().); // finish the course takes two seconds Thread.sleep (2000L ); System.out.println ( "end run to reach the end" + Thread.currentThread () getName ().); latch.countDown(); } catch (InterruptedException e) { e.printStackTrace (); } }, "t1").start(); new Thread(()->{ try { System.out.println ( "trying to run" + Thread.currentThread () getName ().); // finish the course takes five seconds Thread.sleep (5000L ); System.out.println ( "end run to reach the end" + Thread.currentThread () getName ().); latch.countDown(); } catch (InterruptedException e) { e.printStackTrace (); } }, "T2" ) .start (); // 0.1 seconds just sleep that the print bit string no practical effect the Thread.sleep (100 ); System.out.println ( "wait for the last player to finish" ); latch.await(); System.out.println ( "everyone has to finish the end of the game" ); } operation result: Trying to run t1 Trying to run t2 Waiting for the last player to finish End run to reach the terminal t1 Run to reach the terminal end of t2 End of the game everyone has to finish
latch.await () will block the main thread until the last person to finish, before announcing the end of the game
Summary: This example can be used to execute multiple threads simultaneously, but a final report after completion of thread execution results, avoid polling query whether all threads are executed, of course, in addition there are many implementations, such as it is used to resolve this CompletableFuture kind of problem, this article is not too much to explain
Source analysis method :
1. Constructors CountDownLatch (int count), have knowledge of the AQS is very easy to understand the code below is actually a set of state
public CountDownLatch(int count) { if (count < 0) throw new IllegalArgumentException("count < 0"); this.sync = new Sync(count); } // the AQS state set value COUNT Sync ( int COUNT) { setState(count); } protected final void setState(int newState) { state = newState; }
2. blocking method latch.await ()
AQS use shared lock principle, if the AQS state property is not 0, then the current thread node into the AQS wait queue and wait mode is set to shared mode (with the first spread in unlocking achieve shared), and blocks the current thread of execution
类 CountDownLatch public void await() throws InterruptedException { sync.acquireSharedInterruptibly(1); } Class CountDownLatch.Sync public Final void acquireSharedInterruptibly ( int Arg) throws InterruptedException { IF (Thread.interrupted ()) the throw new new ; InterruptedException () // The following piece of code can be seen as the initial count state attempt to acquire the lock // the case if the state is not changed (the countDown () will speak on how to change) is bound to perform doAcquireSharedInterruptibly (Arg) IF (tryAcquireShared (Arg) <0 ) doAcquireSharedInterruptibly (Arg); } // attempt to acquire synchronization lock protected int tryAcquireShared ( int Acquires) { return (getState () == 0). 1: -1? ; } // Get synchronization lock Private void doAcquireSharedInterruptibly ( int Arg) throws InterruptedException { // new node waits Final the Node Node = addWaiter (Node.SHARED); Boolean failed = to true ; the try { for (;;) { Final the Node P = Node .predecessor (); IF (P == head) { int R & lt = tryAcquireShared (Arg); IF (R & lt> = 0 ) { //Node and the node of the heads is shared mode waiting mode (shared mode concept can be found in the article AQS) setHeadAndPropagate (Node, R & lt); p.next = null; // help GC failed = false; return; } } // blocks the current thread IF (shouldParkAfterFailedAcquire (the p-, the Node) && parkAndCheckInterrupt ()) throw new InterruptedException(); } } finally { if (failed) cancelAcquire(node); } }
3.latch.countDown () counting method
AQS using the principle of shared lock released state = 0 when the count of the wait queue thread calls a chain (propagation) of the wake
类 CountDownLatch public void countDown() { sync.releaseShared(1); } Class CountDownLatch.Sync // shared locks are released (not necessarily just tried successfully released) public Final Boolean releaseShared ( int Arg) { // try to release shared locks when the count equals 0 tryReleaseShared (arg) is equal to true IF (tryReleaseShared (Arg)) { doReleaseShared(); return true; } return false; } // try to release shared locks protected Boolean tryReleaseShared ( int Releases) { // of Decrement COUNT; Signal When Transition to ZERO for (;;) { int C = getState (); IF (C == 0 ) return to false ; // count Save a int NEXTC-C =. 1 ; // the atomic state = nextc then returns NEXTC i.e. atomic operation state is equal to 0 iF (compareAndSetState (C, NEXTC)) return NEXTC == 0 ; } } // release the shared lock this period will not speak in detail to do is share lock release // if the current node waitStatus = -3 then continue to spread to the next node // Caught waitStatus = -3 skip continues to spread to the next node, then reached wake up threads on all nodes Private void doReleaseShared () { for (;;) { Node h = head; if (h != null && h != tail) { int ws = h.waitStatus; if (ws == Node.SIGNAL) { if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0)) continue; // loop to recheck cases unparkSuccessor(h); } else if (ws == 0 && !compareAndSetWaitStatus(h, 0, Node.PROPAGATE)) continue; // loop on failed CAS } if (h == head) // loop if head changed break; } }
Summary :
CountDownLatch underlying principle of using a AQS, if mastered AQS CountDownLatch principle is easy to understand