面试题:什么是 Java 的 CyclicBarrier?

CyclicBarrier 是 Java 并发包 (java.util.concurrent) 中的一个同步工具类,用于让一组线程互相等待,直到所有线程都到达某个屏障点(Barrier Point)后再继续执行。它可以用于多线程任务的分阶段执行,特别适合需要多个线程协同工作的场景。


核心概念

  1. 屏障点(Barrier Point)
    • 所有线程必须等待其他线程到达屏障点后才能继续执行。
    • 类似于多人集合后一起出发的场景。
  2. 可重用性
    • CyclicBarrier 是可重用的,当所有线程到达屏障点后,屏障会被重置,可以继续用于下一轮任务。
  3. 回调任务
    • 可以指定一个回调任务(Runnable),当所有线程到达屏障点时,由最后一个到达的线程执行该任务。

常用方法

  1. CyclicBarrier(int parties)
    • 构造函数,创建一个 CyclicBarrier,指定需要等待的线程数量。
  2. CyclicBarrier(int parties, Runnable barrierAction)
    • 构造函数,指定需要等待的线程数量和一个回调任务。
  3. await()
    • 线程调用此方法表示已到达屏障点,并等待其他线程到达。
    • 如果当前线程是最后一个到达屏障点的线程,则会执行回调任务(如果有)。
  4. reset()
    • 重置屏障,使其恢复到初始状态。

使用场景

  1. 多线程任务分阶段执行
    • 例如,多个线程分别处理数据的一部分,处理完成后需要等待其他线程完成,再进行下一阶段的任务。
  2. 并行计算
    • 在并行计算中,多个线程分别计算结果,最后需要汇总所有结果。
  3. 模拟测试
    • 在测试中模拟多个客户端同时发起请求的场景。

代码示例

以下是一个简单的 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 任务完成

注意事项

  1. 线程数量
    • 初始化时设置的线程数量必须与实际调用 await() 的线程数量一致,否则线程会一直等待。
  2. 异常处理
    • 如果某个线程在等待过程中被中断或超时,CyclicBarrier 会抛出 BrokenBarrierException,其他线程也会收到该异常。
  3. 重置屏障
    • 如果需要重新使用 CyclicBarrier,可以调用 reset() 方法重置屏障。

与 CountDownLatch 的区别

  1. 可重用性
    • CyclicBarrier 是可重用的,而 CountDownLatch 是一次性的。
  2. 回调任务
    • CyclicBarrier 支持在所有线程到达屏障点时执行回调任务,CountDownLatch 不支持。
  3. 使用场景
    • CyclicBarrier 适用于多线程分阶段任务,CountDownLatch 适用于主线程等待多个子线程完成任务。

总结

CyclicBarrier 是 Java 并发编程中用于多线程协同工作的重要工具,适用于分阶段任务执行、并行计算等场景。通过合理使用 CyclicBarrier,可以简化多线程编程的复杂性,提高代码的可读性和可维护性。

THE END
点赞7 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容