CyclicBarrier
是 Java 并发包 (java.util.concurrent
) 中的一个同步工具类,用于让一组线程互相等待,直到所有线程都到达某个屏障点(Barrier Point)后再继续执行。它可以用于多线程任务的分阶段执行,特别适合需要多个线程协同工作的场景。
核心概念
- 屏障点(Barrier Point):
- 所有线程必须等待其他线程到达屏障点后才能继续执行。
- 类似于多人集合后一起出发的场景。
- 可重用性:
CyclicBarrier
是可重用的,当所有线程到达屏障点后,屏障会被重置,可以继续用于下一轮任务。
- 回调任务:
- 可以指定一个回调任务(
Runnable
),当所有线程到达屏障点时,由最后一个到达的线程执行该任务。
- 可以指定一个回调任务(
常用方法
CyclicBarrier(int parties)
:- 构造函数,创建一个
CyclicBarrier
,指定需要等待的线程数量。
- 构造函数,创建一个
CyclicBarrier(int parties, Runnable barrierAction)
:- 构造函数,指定需要等待的线程数量和一个回调任务。
await()
:- 线程调用此方法表示已到达屏障点,并等待其他线程到达。
- 如果当前线程是最后一个到达屏障点的线程,则会执行回调任务(如果有)。
reset()
:- 重置屏障,使其恢复到初始状态。
使用场景
- 多线程任务分阶段执行:
- 例如,多个线程分别处理数据的一部分,处理完成后需要等待其他线程完成,再进行下一阶段的任务。
- 并行计算:
- 在并行计算中,多个线程分别计算结果,最后需要汇总所有结果。
- 模拟测试:
- 在测试中模拟多个客户端同时发起请求的场景。
代码示例
以下是一个简单的 CyclicBarrier
示例,模拟多个线程分阶段执行任务:
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierExample {
public static void main(String[] args) {
// 创建一个 CyclicBarrier,等待 3 个线程到达屏障点
CyclicBarrier barrier = new CyclicBarrier(3, () -> {
System.out.println("所有线程已到达屏障点,开始执行下一阶段任务");
});
// 创建 3 个线程
for (int i = 0; i < 3; i++) {
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + " 开始执行第一阶段任务");
Thread.sleep(1000); // 模拟任务执行
System.out.println(Thread.currentThread().getName() + " 到达屏障点,等待其他线程");
barrier.await(); // 等待其他线程
System.out.println(Thread.currentThread().getName() + " 开始执行第二阶段任务");
Thread.sleep(1000); // 模拟任务执行
System.out.println(Thread.currentThread().getName() + " 到达屏障点,等待其他线程");
barrier.await(); // 等待其他线程
System.out.println(Thread.currentThread().getName() + " 任务完成");
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}
}
输出结果:
Thread-0 开始执行第一阶段任务
Thread-1 开始执行第一阶段任务
Thread-2 开始执行第一阶段任务
Thread-0 到达屏障点,等待其他线程
Thread-1 到达屏障点,等待其他线程
Thread-2 到达屏障点,等待其他线程
所有线程已到达屏障点,开始执行下一阶段任务
Thread-0 开始执行第二阶段任务
Thread-1 开始执行第二阶段任务
Thread-2 开始执行第二阶段任务
Thread-0 到达屏障点,等待其他线程
Thread-1 到达屏障点,等待其他线程
Thread-2 到达屏障点,等待其他线程
所有线程已到达屏障点,开始执行下一阶段任务
Thread-0 任务完成
Thread-1 任务完成
Thread-2 任务完成
注意事项
- 线程数量:
- 初始化时设置的线程数量必须与实际调用
await()
的线程数量一致,否则线程会一直等待。
- 初始化时设置的线程数量必须与实际调用
- 异常处理:
- 如果某个线程在等待过程中被中断或超时,
CyclicBarrier
会抛出BrokenBarrierException
,其他线程也会收到该异常。
- 如果某个线程在等待过程中被中断或超时,
- 重置屏障:
- 如果需要重新使用
CyclicBarrier
,可以调用reset()
方法重置屏障。
- 如果需要重新使用
与 CountDownLatch
的区别
- 可重用性:
CyclicBarrier
是可重用的,而CountDownLatch
是一次性的。
- 回调任务:
CyclicBarrier
支持在所有线程到达屏障点时执行回调任务,CountDownLatch
不支持。
- 使用场景:
CyclicBarrier
适用于多线程分阶段任务,CountDownLatch
适用于主线程等待多个子线程完成任务。
总结
CyclicBarrier
是 Java 并发编程中用于多线程协同工作的重要工具,适用于分阶段任务执行、并行计算等场景。通过合理使用 CyclicBarrier
,可以简化多线程编程的复杂性,提高代码的可读性和可维护性。
THE END
暂无评论内容