0%

CountDownLatch

CountDownLatch 定义了一个计数器,和一个阻塞队列, 当计数器的值递减为0之前,阻塞队列里面的线程处于挂起状态,当计数器递减到0时会唤醒阻塞队列中所有线程,它可以解决那些一个或者多个线程在执行之前必须依赖于某些必要的前提业务先执行的场景。


CountDownLatch 常用方法

1
2
3
4
CountDownLatch(int count); // 构造方法,创建一个值为count的计数器
await(); // 阻塞当前线程,将当前线程加入阻塞队列
await(long timeout, TimeUnit unit); // 在timeout的时间之内阻塞当前线程,时间一过则当前线程可以执行
countDown(); // 对计数器进行递减1操作,当计数器递减至0时,会唤醒阻塞队列里的所有线程

测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class CountDownLatchTest {
static int N = 5;
private static final CountDownLatch countDownLatch = new CountDownLatch(N);

public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < N; i++) {
new Thread(() -> {
try {
// do something
System.out.println("子线程:" + Thread.currentThread().getName() + " 任务已完成");
countDownLatch.countDown();
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
// 主线程阻塞
countDownLatch.await();
// 当countDownLatch的count减至0后,被countDownLatch.await()阻塞的线程唤起
System.out.println("主线程:在所有任务运行完成后,进行结果汇总");
}
}

测试结果


原理分析

下面是 CountDownLatch 类的源码

可以看到 CountDownLatch 类搞了个 Sync 的内部类并且继承了 AbstractQueuedSynchronizer ,在创建 CountDownLatch 的时候,通过本身的构造方法调了内部类的构造方法,其中有个方法 setState(count),此方法继承自 AQS ,说白了就是利用 AQS 实现的,关于 AQS 的分析有机会再说吧~