countdownlatch 是 java 中主线程等待多个子线程完成初始化的最简洁可靠方式;它通过初始化时指定线程数、子线程调用 countdown() 递减计数、主线程调用 await() 阻塞等待归零来实现同步,且不可重置,需配合异常处理与超时机制。

使用 CountDownLatch 是 Java 中实现主线程等待多个子线程完成初始化的最简洁、可靠的方式。它本质是一个同步辅助类,允许一个或多个线程等待其他线程完成一组操作。
初始化 CountDownLatch 并传入线程数量
在主线程中创建 CountDownLatch 实例时,构造参数应等于待等待的子线程数。这个数值代表“还需倒数几次才能释放等待线程”。
- 例如:有 3 个子线程负责加载配置、连接数据库、初始化缓存,则初始化为
new CountDownLatch(3) - 计数器初始值不可更改,且只能递减(调用
countDown()),不能重置
子线程完成初始化后调用 countDown()
每个子线程在自身初始化逻辑执行完毕后,必须显式调用 latch.countDown()。这会将内部计数器减 1,但不会阻塞该子线程本身。
- 建议放在 try-finally 块中,确保即使初始化异常也能释放计数器(避免主线程永久挂起)
- 示例:
try { /* 初始化逻辑 */ } finally { latch.countDown(); }
主线程调用 await() 阻塞等待
主线程在启动所有子线程后,立即调用 latch.await()。该方法会阻塞,直到计数器归零或被中断。
- 可选带超时的版本:
latch.await(10, TimeUnit.SECONDS),避免无限等待 - 若超时或被中断,
await()返回false或抛出InterruptedException,需合理处理失败场景
注意异常与资源清理
CountDownLatch 本身不处理子线程异常,主线程无法直接获知哪个子线程失败。如需错误传播,应配合 Future 或共享状态变量(如 AtomicReference<exception></exception>)。
- 主线程可通过检查计数器是否为 0 判断是否全部完成:
latch.getCount() == 0 - 不建议重复使用同一实例;如需多次等待,应新建
CountDownLatch或改用CyclicBarrier
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











