countDownLatch这个类使一个线程等待其他线程都执行完毕之后再执行。使通过一个计数器来实现的,计数器的初始值是线程的数量,每当一个线程执行完毕之后,调用countDown方法,计算器值减1,当计数器的值为0时,表示所有线程都执行完毕了,等待的线程就可以恢复工作了。
简单示例:
public class countDownLatchTest { public static void main(String[] args) throws InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(3); new Thread(() -> { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("countDownLatch减1"); countDownLatch.countDown(); }).start(); new Thread(() -> { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("countDownLatch减1"); countDownLatch.countDown(); }).start(); new Thread(() -> { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("countDownLatch减1"); countDownLatch.countDown(); }).start(); countDownLatch.await(); System.out.println("3个线程都执行完了,主线程可以恢复执行了。"); } }
执行结果,countDownLatch要从3一直减到0,主线程才可以执行,否则主线程一直在等待:
分析源码,看看countDown的实现:
/** * Decrements the count of the latch, releasing all waiting threads if * the count reaches zero. * * <p>If the current count is greater than zero then it is decremented. * If the new count is zero then all waiting threads are re-enabled for * thread scheduling purposes. * * <p>If the current count equals zero then nothing happens. */ public void countDown() { sync.releaseShared(1); }
Sync继承了AbstractQueuedSynchronizer(AQS)。AQS的其中一个作用就是维护线程状态和获取释放锁。在这里也就是说CountDownLatch使用AQS机制维护锁状态。而releaseShared(1)方法就是释放了一个共享锁。
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) { // Decrement count; signal when transition to zero for (;;) { int c = getState(); if (c == 0) return false; int nextc = c-1; if (compareAndSetState(c, nextc)) return nextc == 0; } } }
再看看await的实现:
public void await() throws InterruptedException { sync.acquireSharedInterruptibly(1); } public final void acquireSharedInterruptibly(int arg) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); if (tryAcquireShared(arg) < 0) doAcquireSharedInterruptibly(arg); } /** * Acquires in shared interruptible mode. * @param arg the acquire argument */ private void doAcquireSharedInterruptibly(int arg) throws InterruptedException { final Node node = addWaiter(Node.SHARED); boolean failed = true; try { for (;;) { final Node p = node.predecessor(); if (p == head) { int r = tryAcquireShared(arg); if (r >= 0) { setHeadAndPropagate(node, r); p.next = null; // help GC failed = false; return; } } if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) throw new InterruptedException(); } } finally { if (failed) cancelAcquire(node); } }