CountDownLatch 使用方式
作为程序员,面试被问“CountDownLatch 怎么用?”简直家常便饭。今天咱就掰开揉碎讲明白,让你面试直接拿分!
附:2025年Java面试高频题合集
🔗 链接: https://pan.baidu.com/s/1RUVf75gmDVsg8MQp4yRChg?pwd=9b3g
提取码:9b3g
一、CountDownLatch 是干啥的?
简单说,它就是个线程协调工具。想象你组队打副本:5个队友必须全部到齐,队长才能开团。CountDownLatch 就是这个“队长”——它用数字倒计时卡住主线程,直到所有子线程完成任务。

(多线程任务协调示意图)
二、核心使用方式四步走
面试官最想听你理清逻辑,直接上步骤:
步骤1:初始化倒计数器
CountDownLatch latch = new CountDownLatch(3); // 参数3=需要3个线程完成任务
这里数字代表需要等待的线程数量,比如要等3个文件下载完再合并。
步骤2:子线程调用 countDown()
每个线程完成任务后调用:
public void run() {
// ... 执行下载任务
latch.countDown(); // 倒计时-1
}
关键点:countDown()要放在 finally 块!避免线程异常导致主线程死等。
步骤3:主线程调用 await()
主线程在需要阻塞的地方“蹲守”:
latch.await(); // 卡在这里,直到计数器归零
// 所有线程完成后,继续执行合并文件
支持超时机制:await(10, TimeUnit.SECONDS) 防止死锁。
步骤4:检查计数器状态
通过getCount()查看剩余任务数,调试时很有用。
三、经典面试场景举例
场景1:大数据分片处理
“我有100W数据切分10份,10个线程并行处理,全部处理完再入库。”
CountDownLatch latch = new CountDownLatch(10);
for(int i=0; i<10; i++){
new Thread(() -> {
processData();
latch.countDown();
}).start();
}
latch.await();
saveToDB(); // 确保所有分片处理完才执行
场景2:服务启动依赖检查
“支付服务启动前,必须确认账户服务、风控服务、日志服务都就绪。”
四、避坑指南(面试加分项!)
- 复用问题:
CountDownLatch 倒计时到0后就不能重置了!想循环用?选 CyclicBarrier。 - 异常处理:
子线程异常时一定要在finally中调用countDown(),否则主线程永远阻塞。 - 性能陷阱:
线程数别设置太大(比如10W+),await()会竞争锁,影响性能。
五、对比其他同步工具
| 工具 | 特点 | 适用场景 |
|---------------------|------------------------------|--------------------------|
| CountDownLatch | 一次性的,主等子 | 启动依赖、分批任务汇总 |
| CyclicBarrier | 可重置的,子等子 | 分阶段并行计算 |
| Semaphore | 控制资源并发量 | 数据库连接池限流 |
六、高频面试题(附解题思路)
Q:CountDownLatch 和 join() 有什么区别?
A:join() 只能等单个线程,CountDownLatch 能灵活控制多个线程,还能设置超时!
Q:计数器为0后,再调用 await() 会怎样?
A:立刻放行!因为此时计数器已经是0了,不会阻塞。
Q:子线程还没执行完,主线程就继续了,可能是什么原因?
A:大概率是
latch.countDown()被提前调用了,比如在子线程开头就写了。
💡 小贴士:若想获取最新Java面试题库或面试鸭会员优惠,可访问 面试鸭返利网。通过该站联系我,购买会员可返利 25 元!

(小提示:实际开发中,CompletableFuture 处理异步任务更灵活,但面试必问 CountDownLatch!)



