在 Java 中,CyclicBarrier
和 CountDownLatch
都是来自 java.util.concurrent
包的并发同步工具,但它们的用途、行为方式 和 可重用性 不同。下面详细对比两者的差异:
🧩 1. 核心用途与工作原理
特性 |
|
|
目标 | 让一组线程相互等待,直到所有线程都到达某个共同屏障点 | 一个或多个线程等待,直到其他线程完成操作 |
触发方式 | 所有线程都调用 | 主线程或其它线程调用 |
典型场景 | 多个线程并行处理任务后再统一继续,如多阶段并行计算 | 等待多个服务或资源初始化完成后再执行操作,如系统启动 |
🔄 2. 是否可重用
CyclicBarrier
是可重用的:
- 每次到达屏障点后会自动重置,可以用于多次阶段性同步。
- 适合迭代性场景,如模拟多个线程逐步推进阶段。
CountDownLatch
是一次性的:
- 计数器只减不增,用完即废(不能重置)。
- 需要重新创建实例才能再次使用。
⏱ 3. 构造函数参数
CyclicBarrier(int parties)
或CyclicBarrier(int parties, Runnable barrierAction)
parties
: 参与线程数barrierAction
: 所有线程到达屏障后执行的任务(可选)
CountDownLatch(int count)
count
: 需完成的线程/任务数量
🚦 4. 示例比较
✅ CountDownLatch 示例:
CountDownLatch latch = new CountDownLatch(3);
new Thread(() -> {
// 子任务 1
latch.countDown();
}).start();
new Thread(() -> {
// 子任务 2
latch.countDown();
}).start();
new Thread(() -> {
// 子任务 3
latch.countDown();
}).start();
// 主线程等待所有任务完成
latch.await();
System.out.println("所有任务已完成!");
🔁 CyclicBarrier 示例:
CyclicBarrier barrier = new CyclicBarrier(3, () -> {
System.out.println("所有线程到达屏障,执行统一任务");
});
Runnable task = () -> {
// 独立处理任务
barrier.await(); // 等待其他线程
// 所有线程统一继续
};
new Thread(task).start();
new Thread(task).start();
new Thread(task).start();
📌 5. 总结对比
特性 |
|
|
用于线程间协同 | ✅ | ❌ |
用于线程间等待其他线程完成 | ❌ | ✅ |
是否可重用 | ✅ | ❌ |
提供统一执行操作(barrier action) | ✅ | ❌ |
常用于 | 分阶段任务 | 等待资源初始化等 |