countdownlatch 是 java 并发包中用于等待一组线程完成的同步工具,主线程调用 await() 阻塞,子线程执行完调用 countdown() 减计数,初始化时指定正整数计数值,计数归零后不可重用。

CountDownLatch 是 Java 并发包(java.util.concurrent)中一个轻量级的同步工具,专为“等待一组线程完成”这种场景设计。它的核心思想是:主线程调用 await() 阻塞等待,直到内部计数器减到 0;而每个子线程执行完任务后调用 countDown() 将计数器减 1。
初始化时指定子线程数量
创建 CountDownLatch 实例时,必须传入一个正整数,代表需要等待的子线程个数(即初始计数值):
CountDownLatch latch = new CountDownLatch(3); // 等待 3 个子线程
这个数字不一定要等于实际启动的线程数,但通常应保持一致。如果少于实际线程数,可能提前唤醒主线程;如果多于,则主线程会一直阻塞(除非超时)。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
子线程执行完后调用 countDown()
每个子线程在自己逻辑结束前,必须调用一次 latch.countDown()。这一步是非阻塞的,仅递减计数器:
- 即使多次调用
countDown(),计数器也不会变成负数(最小为 0) - 推荐放在
finally块中,确保异常时也能触发计数 - 示例:
new Thread(() -> {
try {
// 执行耗时操作
System.out.println("子线程开始工作");
Thread.sleep(1000);
System.out.println("子线程完成");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
latch.countDown(); // 关键:务必执行
}
}).start();
主线程调用 await() 等待全部完成
主线程在启动所有子线程后,立即调用 latch.await()。此时它会挂起,直到计数器归零或被中断:
-
latch.await():无限等待,直到计数为 0 或当前线程被中断 -
latch.await(long timeout, TimeUnit unit):带超时,避免永久阻塞(推荐生产环境使用) - 返回
true表示计数归零;false表示超时未完成
System.out.println("主线程启动子线程...");
// 启动多个子线程...
latch.await(); // 阻塞在此,直到所有子线程调用 countDown()
System.out.println("所有子线程已完成,主线程继续执行");
注意事项与常见误区
-
CountDownLatch 是一次性使用的:计数归零后,
await()不再阻塞,countDown()也不再有效;如需重复使用,考虑CyclicBarrier -
不要依赖线程启动顺序:主线程应在所有
start()调用完成后才调用await(),否则可能漏等 -
异常处理要到位:子线程中若抛出未捕获异常,
countDown()可能不会执行,导致主线程永远等待 -
避免在 await() 前就关闭线程池或释放资源:确保子线程有足够机会执行并调用
countDown()
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










