CountDownLatch literally as “reciprocal valve”, as the name suggests, it is a function of the valve, in fact, is used to control the thread of the implementation process. See what the class provides:


It can be seen from the figure, the construction method of CountDownLatch is introduced into an integer, and then provides the await (), countDown (), getCount () method, and an internal Sync, the internal class inherits AbstractQueuedSynchronizer.
the kernel of the entire CountDownLatch is the Sync class, first look at this class.


Private static final class Sync extends AbstractQueuedSynchronizer {/ / inherits the AQS class private static final long serialVersionUID = 4982264981922014374L; Sync (int count) {/ / constructor in AQS state is set to the value of count setState (count) int (getCount) {}; / / get the value of state return (getState);} / * * * override the AQS of the tryAcquireShared * attempts to acquire a shared lock, if the current state is equal to 0 return 1 if successful, otherwise it returns -1 / protected int tryAcquireShared failure (int acquires) {return (getState) = (0)? 1: -1;} / * * * AQS tryReleaseShared * / protected rewriting (int releases Boolean tryReleaseShared {) Signal when / / Decrement count; transition to zero for (;;) {/ / dead circulation, ensure that CAS int c = getState (successfully changed); if (C = = 0) / / if the current state is 0, return false int nextc failed to release; = C-1; / / state - 1 if (compareAndSetState (C, nextc the latest changes)) / / state return nextc = = 0; / / if state - 1 to 0 returns true, otherwise returns false}}}

The Sync class overrides the tryAcquireShared method of AQS and tryReleaseShared in tryAcquireShared, determine the current state is 0, to reduce the operation on the state tryReleaseShared, if state is 0 reduction after it returns true. The methods in
CountDownLatch call the methods in Sync, and then take a look at the implementation of CountDownLatch.

CountDownLatch (int)

/ / construction method, the initialization of sync public CountDownLatch (int count) {/ / if count is less than 0 throws illegalargumentexception if (count < 0) throw new IllegalArgumentException (count < 0); this.sync = new Sync (count);}


There are two kinds of await. One is time limited, and the other is time limited.

AQS acquireSharedInterruptibly * / * * * call or a call to the tryAcquireShared method, it is judged whether the current state is 0 * if not 0 then the current thread into the waiting queue, blocked void await (throws / public) InterruptedException (1) {sync.acquireSharedInterruptibly}; / * * * * tryAcquireSharedNanos AQS call within a specified period of time did not get lock, return false / public Boolean await (long timeout, TimeUnit unit InterruptedException return sync.tryAcquireSharedNanos (throws) {1, unit.toNanos (timeout));}


AQS releaseShared * * / * * call releaseShared call to the tryReleaseShared method in Sync rewriting, state - 1 * if state - 1 to 0, return true, then wake up waiting threads void / public (countDown) {sync.releaseShared} (1);


Based on the understanding of AbstractQueuedSynchronizer, coupled with reading the above source code, we have a clear understanding of the role and principles of CountDownLatch:

  • The inner class CountDownLatch in Sync inherits the AQS, and writes both the tryAcquireShared and tryReleaseShared methods
  • CountDownLatch implements the encapsulation of AQS shared lock methods, equivalent to changing an intuitive name
  • Execute the await method to determine whether the state is equivalent to the counter, whether it’s 0, and if not 0, the current thread is blocked until state is 0
  • The countDown method is executed to reduce the state operation, and if it is reduced to 0, the waiting thread is awakened

A brief summary is, CountDownLatch is initialized to count valve, said capacity thread executes the await method within the valve without waiting for something (state = = 0), if the valve has something (state > 0), then await method is blocked, there is nothing until the valve (state = 0) was wake up. When a thread executes the countDown method, the valve things will reduce a (state = state – 1), if a valve does not reduce after things, just wake up waiting for the empty thread valve.
more vivid point, for example, there is a public bath, bath with shower head number (count), the shower head have been in use, when someone wanted to take a bath, these people need to wait for all the people have the shower washed (state = = 0), so they have to wait outside (await), whenever there is a person washed (countDown), will look at is not all washed, if all the people had finished washing, then to the outside waiting for the person who said, you can come in, then wait for people to come in (that thread is woken up, continue).

Apply Demo

Import java.util.concurrent.CountDownLatch; public class CountDownLatchTest private static final int {numOfThreads = 10; / / private static final int sleepTime thread number = 3000; / / public static void main sleep (String[] args) {CountDownLatch startLatch = new CountDownLatch (1) (start.countDown); / / only execution thread to execute CountDownLatch (CountDownLatch threadLatch = New numOfThreads for (int); I = 0; I < numOfThreads; i++) {new Thread (New) Runnable (@Override public void run () {{{startLatch.await (try); / / wait for the startLatch.countDown to perform Thread.sle EP (sleepTime); System.out.println (Thread.currentThread) (.GetName ());} catch (InterruptedException E) {e.printStackTrace}); (threadLatch.countDown); / / (complete thread number -1 (.Start));}}} (startLatch.countDown); / / all threads started long start = (System.currentTimeMillis; try) {threadLatch.await (); / / wait for the completion of the execution of all threads (InterruptedException E) {catch}} (e.printStackTrace); System.out.println (numOfThreads + "thread completes the time:" + (System.currentTimeMillis) - (start) + "Ms"); }}

Execution results are:

Thread-8 Thread-9, Thread-5, Thread-3, Thread-1, Thread-0, Thread-2, Thread-4, Thread-7, Thread-6, 10 threads, execution time spent: ms