在多线程开发中,CountDownLatch和CyclicBarrier都能协调线程步调,但设计理念不同。CountDownLatch是一次性倒计时器,而CyclicBarrier是可重用的栅栏。理解它们的差异有助于写出更清晰的并发逻辑。

核心机制对比
CountDownLatch初始化一个固定计数,工作线程调用countDown让计数减一,等待线程调用await阻塞直到计数归零。计数到零后 latch 失效,无法再次使用。
CyclicBarrier设定参与线程数,每个线程到达屏障点调用await,当所有线程都到达后屏障打开,线程继续,同时屏障自动重置,可进入下一轮。
主要差异点
- 重用性:CountDownLatch不可重置,CyclicBarrier可循环使用
- 角色:前者区分计数线程与等待线程,后者所有线程对等
- 异常:屏障损坏后CyclicBarrier会抛BrokenBarrierException
代码示例
CountDownLatch用法
import java.util.concurrent.CountDownLatch;
public class LatchDemo {
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(2);
// 两个工作线程
new Thread(() -> {
System.out.println("任务A完成");
latch.countDown();
}).start();
new Thread(() -> {
System.out.println("任务B完成");
latch.countDown();
}).start();
// 主线程等待
latch.await();
System.out.println("所有任务结束,开始汇总");
}
}
CyclicBarrier重用示例
import java.util.concurrent.CyclicBarrier;
public class BarrierDemo {
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(2, () -> {
System.out.println("一轮结束,屏障重置");
});
Runnable task = () -> {
for (int i = 0; i < 2; i++) {
try {
System.out.println(Thread.currentThread().getName() + "到达");
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
}
};
new Thread(task, "T1").start();
new Thread(task, "T2").start();
}
}
如何选择
如果只需等待一批任务完成再继续,用CountDownLatch更简单。若业务需要多轮同步,比如并行计算分阶段汇总,CyclicBarrier的重用特性会减少对象创建和代码复杂度。
| 维度 | CountDownLatch | CyclicBarrier |
|---|---|---|
| 是否可重用 | 否 | 是 |
| 线程角色 | 分离 | 对等 |
| 重置方式 | 无 | 自动 |
简单说,倒计时用于等别人干完,栅栏用于大家互相等齐再走,且能反复走。
CountDownLatchCyclicBarrier并发控制修改时间:2026-07-26 08:30:17