CountDownLatch

CountDownLatch 类存在一个内部类 Sync 继承自 AbstractQueueSynchronizer

所以 CountDownLatch 也是基于 AQS 实现的,其中 state 表示前面有几个线程需要等待

核心函数

内部类结构

类中只有一个成员变量 Sync 这个类继承了 AbstractQueueSynchronizer

1
2
3
4
public class CountDownLatch {
// 同步队列
private final Sync sync;
}

类的构造函数

调用了 Sync 的构造方法, Sync 又调用了父类 AQS 的方法, 设置了 state 值

1
2
3
4
5
6
7
8
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
// 其中 Sync 的构造函数调用了父类 AQS 的方法, 设置了 AQS 中的 state 值
Sync(int count) {
setState(count);
}

await 函数

此函数将会使当前线程在锁存器倒计数至 0 之前一直等待, 除非线程被中断

1
2
3
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}

countDown 函数

此函数将递减锁存器的计数, 如果计数达到 0, 则释放所有等待线程

1
2
3
public void countDown() {
sync.releaseShared(1);
}

使用案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(10);
CountDownLatch countDownLatch = new CountDownLatch(10);
for (int i = 0; i < 10; i++) {
executorService.execute(() -> {
try {
System.out.println(Thread.currentThread().getName() + " is running...");
// 每个线程睡 1s
Thread.sleep(1000);
} catch (InterruptedException e) {
// ignore
} finally {
// 休眠完之后 countDownLatch - 1
countDownLatch.countDown();
}
});
}
// 只有 countDownLatch 减到 0 的时候才会停止阻塞
countDownLatch.await();
executorService.shutdown();
System.out.println("end...");
}

记得最后要调用 shutdown() 否则线程永远不会结束

因为线程池的线程处于 waiting 状态,他们作为 GC Root 不会被回收


CountDownLatch
http://showyoubug.cn/2024/08/10/CountDownLatch/
作者
Dong Su
发布于
2024年8月10日
许可协议