CountDownLatch 是基于计数器的同步工具,用于主线程等待多个子线程完成:初始化时设准确线程数,子线程在 finally 中调用 countDown(),主线程调用带超时的 await() 并处理返回值与异常,其不可重用且需保障共享数据线程安全。

CountDownLatch 是 Java 并发包中一个轻量、实用的同步工具,特别适合“主线程等待多个子线程完成任务后再继续执行”的场景。它的核心是内部一个计数器,调用 countDown() 递减,调用 await() 阻塞直到计数归零。
初始化 CountDownLatch,数量等于子线程个数
在启动子线程前,先创建 CountDownLatch 实例,并把计数值设为预期并发执行的子线程数量。这个数字必须准确——少设会导致主线程提前结束;多设会永远阻塞(除非超时)。
- 例如:要等 3 个数据加载线程,就写
new CountDownLatch(3) - 如果子线程数量动态变化(如从列表循环创建),务必在循环前计算好总数并传入
每个子线程完成任务后调用 countDown()
子线程内业务逻辑执行完毕(无论成功或失败),都应确保调用一次 latch.countDown()。推荐放在 finally 块中,避免因异常跳过导致计数不减、主线程永久等待。
- 错误写法:
if (success) latch.countDown();—— 异常时不触发,风险高 - 正确写法:
try { /* 加载逻辑 */ } finally { latch.countDown(); }
主线程调用 await() 等待所有子线程完成
主线程在启动全部子线程后,立即调用 latch.await()。该方法会阻塞当前线程,直到计数器变为 0 或被中断。
- 建议使用带超时的版本:
latch.await(10, TimeUnit.SECONDS),防止因子线程卡死导致主线程无限等待 - 检查返回值:若超时返回
false,可做降级处理(如用默认数据、记录告警) - 若被中断,会抛出
InterruptedException,需捕获并合理处理(如恢复中断状态)
注意线程安全与资源释放
CountDownLatch 本身线程安全,但共享的数据(如结果容器)需要额外保护。常见做法是用线程安全集合(ConcurrentHashMap、CopyOnWriteArrayList),或加锁收集结果。
- 不要在子线程中直接修改非线程安全的
ArrayList或普通Map - 若需汇总结果,可让每个子线程返回
Future,或用AtomicInteger计数+同步块更新结果 - CountDownLatch 不可重用,计数归零后再次
await()会立即返回










