Last updated on 2025-11-23T21:12:29+08:00
1. TODO
2. 脑图
Xmind
Edraw
Hexo 地址
👉 http://blog.wangjia.ink/2025/11/16/源码:java.util.concurrent.CountDownLatch源码解析/
3. 基础部分
3.1. CountDownLatch 概述
CountDownLatch 是一个具体类
倒计时门闩(CountDownLatch)是使用 AQS 实现的共享模式的同步器。State 和共享资源分别表示以下含义:
State 表示门闩是否开启
0
- 门闩开启
n(n > 0)
- 门闩关闭
- 共享资源表示门闩开启后,被允许执行的操作
我们可以将 CountDownLatch 简单的理解为:一次性的、只做减法的计数器。
[!NOTE] 注意事项
- 简单理解
CountDownLatch、CyclicBarrier、Semaphore:
CountDownLatch 是门闩开启才能继续执行
CyclicBarrier 是 “互相等待” 都准备好才能继续执行
Semaphore 是拿到 “许可证” 才能继续执行
3.2. CountDownLatch 应用场景
3.2.1. 汇总模式
汇总模式是指:主线程等待多个子线程准备好后,才能继续执行
我们可以简单的理解为:主线程等待,子线程减数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public class Test { public static void main(String[] args) throws InterruptedException { CountDownLatch myCountDownlatch = new CountDownLatch(3); for (int i = 0; i < 3; i++) { int finalI = i; new Thread(() -> { System.out.println(finalI); myCountDownlatch.countDown(); }).start(); } myCountDownlatch.await(); System.out.println("天下贤才尽数会于麾下!"); } }
|
3.2.2. 发令枪模式
发令枪模式是指:多个子线程准备好后,等待主线程 “发枪”,才能继续执行
我们可以简单的理解为:子线程等待,主线程减数
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
| public class Test { public static void main(String[] args) throws InterruptedException { CountDownLatch myCountDownlatch = new CountDownLatch(1); for (int i = 0; i < 3; i++) { int finalI = i; new Thread(() -> { try { myCountDownlatch.await(); System.out.println(finalI); myCountDownlatch.countDown(); } catch (InterruptedException e) { throw new RuntimeException(e); } }).start(); } Thread.sleep(1000); System.out.println("天下贤才尽数听令而动!"); myCountDownlatch.countDown(); } }
|
4. 源码部分
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
| public class CountDownLatch { private static final class Sync extends AbstractQueuedSynchronizer { 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(); } public String toString() { return super.toString() + "[Count = " + sync.getCount() + "]"; } }
|