countdownlatch 是一次性同步工具,通过计数器协调线程等待:构造时指定正整数初始值,await() 阻塞线程直至计数归零,countdown() 递减计数;不可重置,适用于主线程等待多个子任务完成的场景。

CountDownLatch 是 Java 并发包中用于线程间协同等待的同步辅助类,核心作用是让一个或多个线程等待,直到其他线程完成一组操作。 它内部维护一个计数器,每次调用 countDown() 递减,当计数器归零时,所有因 await() 阻塞的线程被唤醒并继续执行。它是一次性使用的,不可重置。
理解 CountDownLatch 的基本构造和关键方法
创建时需指定初始计数值(正整数),代表需要等待的“事件数量”或“前置任务数量”:
-
CountDownLatch latch = new CountDownLatch(3);—— 表示需等待 3 个信号 -
latch.await();—— 当前线程阻塞,直到计数为 0;可设超时(await(long, TimeUnit))避免永久等待 -
latch.countDown();—— 计数减 1;通常由工作线程在完成任务后调用
典型使用场景:主线程等待多个子任务完成
例如启动 5 个异步任务处理数据,主线程需等全部结束才汇总结果:
- 初始化
CountDownLatch latch = new CountDownLatch(5); - 每个子线程执行完自己的逻辑后调用
latch.countDown(); - 主线程在启动所有子线程后立即调用
latch.await();,挂起等待 - 当第 5 次
countDown()执行后,计数归零,主线程被唤醒,继续后续逻辑
注意线程安全与常见陷阱
CountDownLatch 本身是线程安全的,但使用中容易出错:
- 不要在未完成的线程里漏掉
countDown(),否则await()会一直阻塞 - 避免在同一个线程中多次调用
countDown()导致计数过早归零(除非业务确实需要) - 如果想支持重复使用,请改用
CyclicBarrier;CountDownLatch不可重置 - 建议配合 try-finally 使用,确保异常情况下也能触发
countDown()(尤其在复杂流程中)
结合实际代码片段理解
以下是一个简明示例:
CountDownLatch latch = new CountDownLatch(3);
for (int i = 0; i {
try {
System.out.println(Thread.currentThread().getName() + " 开始工作");
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + " 完成");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
latch.countDown(); // 确保释放许可
}
}).start();
}
System.out.println("主线程等待所有子线程完成...");
latch.await(); // 阻塞直到 count == 0
System.out.println("全部完成,主线程继续执行");
不复杂但容易忽略细节。关键是把“谁负责倒计时”和“谁负责等待”分清楚,再配合适当的异常保护,就能稳定实现多线程协同等待。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











