一、介绍 一种同步辅助,允许一个或多个线程等待其他线程中执行的一组操作完成。
CountDownLatch使用给定的计数初始化。由于调用了countDown方法,await方法一直阻塞到当前计数为零,在此之后,所有等待线程被释放,await的任何后续调用立即返回。这是一种一次性现象——计数无法重置。如果您需要一个可以重置计数的版本,请考虑使用CyclicBarrier。
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public static void main (String[] args) throws InterruptedException { final CountDownLatch c = new CountDownLatch (2 ); new Thread (new Runnable () { @Override public void run () { c.countDown(); System.out.println("线程1执行完成" ); } }).start(); new Thread (new Runnable () { @Override public void run () { c.countDown(); System.out.println("线程2执行完成" ); } }).start(); c.await(); System.out.println("退出" ); }
结果:
CountDownLatch的构造函数接收一个,其中构造参数n表示等待n个完成,即执行countDown n次。
二、源码分析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 public class CountDownLatch { private static final class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = 4982264981922014374L ; Sync(int count) { setState(count); } int getCount () { return getState(); } protected int tryAcquireShared (int acquires) { return (getState() == 0 ) ? 1 : -1 ; } protected boolean tryReleaseShared (int releases) { for (;;) { int c = getState(); if (c == 0 ) return false ; int nextc = c-1 ; if (compareAndSetState(c, nextc)) return nextc == 0 ; } } } private final Sync sync; public CountDownLatch (int count) { if (count < 0 ) throw new IllegalArgumentException ("count < 0" ); this .sync = new Sync (count); } public void await () throws InterruptedException { sync.acquireSharedInterruptibly(1 ); } public boolean await (long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireSharedNanos(1 , unit.toNanos(timeout)); } public void countDown () { sync.releaseShared(1 ); } public long getCount () { return sync.getCount(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public abstract class AbstractQueuedSynchronizer { public final void acquireShared (int arg) { if (tryAcquireShared(arg) < 0 ) doAcquireShared(arg); } public final boolean releaseShared (int arg) { if (tryReleaseShared(arg)) { doReleaseShared(); return true ; } return false ; } }
为什么CountDownLatch只能起一次作用而不能重置?
通过上面的源码分析可以看出tryReleaseShared将会把state释放到0,tryAcquireShared则返回-1,acquireShared则不会再进入阻塞