什么是 Java 的 CyclicBarrier?

2024-08-26 08:41:34 341
`CyclicBarrier` 是 Java 中提供的一个同步辅助类,位于 `java.util.concurrent` 包中。它允许一组线程互相等待,直到所有线程都到达某个公共的屏障点(barrier)。`CyclicBarrier` 常用于并发编程中,特别是在需要多线程分阶段处理任务的场景中。

1. CyclicBarrier 的基本概念

  • 屏障(Barrier)CyclicBarrier 设置一个屏障点,当所有参与线程(指定的线程数量)都到达屏障时,屏障会打开,所有线程继续执行。
  • 循环使用CyclicBarrier 可以被重复使用,因此称为“循环的”屏障(cyclic barrier)。每当所有线程都到达屏障点并继续执行后,屏障会被重置,准备下一次使用。

2. CyclicBarrier 的构造方法

CyclicBarrier 提供了两种构造方法:

  • CyclicBarrier(int parties):创建一个新的 CyclicBarrier,它将拦截指定数量(parties)的线程,直到这些线程全部到达屏障点。
  • CyclicBarrier(int parties, Runnable barrierAction):创建一个新的 CyclicBarrier,当所有线程到达屏障点时,先执行一个指定的 barrierAction,然后释放所有线程。

3. 使用示例

以下是一个使用 CyclicBarrier 的简单示例,模拟多个线程同时处理不同部分的数据,当所有线程都处理完毕时,进行汇总处理。

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierExample {
    public static void main(String[] args) {
        int numberOfThreads = 3;
        
        // 创建 CyclicBarrier,指定屏障点线程数量和一个在屏障开启时执行的任务
        CyclicBarrier barrier = new CyclicBarrier(numberOfThreads, () -> {
            System.out.println("All tasks completed. Proceeding to the next step.");
        });

        // 创建并启动多个线程
        for (int i = 0; i < numberOfThreads; i++) {
            new Thread(new Task(barrier)).start();
        }
    }

    static class Task implements Runnable {
        private CyclicBarrier barrier;

        public Task(CyclicBarrier barrier) {
            this.barrier = barrier;
        }

        @Override
        public void run() {
            try {
                // 模拟任务处理
                System.out.println(Thread.currentThread().getName() + " is processing.");
                Thread.sleep((int) (Math.random() * 1000));
                
                // 到达屏障点,等待其他线程
                System.out.println(Thread.currentThread().getName() + " has reached the barrier.");
                barrier.await();
                
                // 继续执行
                System.out.println(Thread.currentThread().getName() + " is continuing.");
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }
}

解释

  1. 线程启动:示例中创建了 3 个线程,它们执行相同的 Task 任务。
  2. 到达屏障:每个线程在执行完任务的第一阶段后,会调用 barrier.await(),表示到达屏障点并等待其他线程。
  3. 屏障打开:当所有线程都调用 await() 后,CyclicBarrier 打开屏障,所有线程继续执行,并打印“is continuing”。
  4. barrierAction:在屏障打开前,执行构造 CyclicBarrier 时指定的任务(打印“All tasks completed. Proceeding to the next step.”)。

4. 应用场景

CyclicBarrier 适合用于以下场景:

  • 多线程分阶段处理:当多个线程需要分阶段执行任务,并且需要在某个阶段结束时同步,CyclicBarrier 可以用于协调线程同步。
  • 并行计算:在科学计算或图像处理等领域,可以使用 CyclicBarrier 将大任务分成多个子任务,多个线程并行执行,最后汇总结果。
  • 模拟多线程系统:在模拟中,可以使用 CyclicBarrier 控制多线程操作,使它们同步执行某些步骤。

5. 与 CountDownLatch 的区别

CyclicBarrierCountDownLatch 都用于线程之间的协调,但它们有一些不同之处:

  • 循环使用CyclicBarrier 可以被重置并循环使用,而 CountDownLatch 只能使用一次。
  • 线程数量CyclicBarrier 控制的是线程到达屏障点的数量,而 CountDownLatch 控制的是倒计数的次数。

总结

CyclicBarrier 是一种用于协调多个线程同时到达一个屏障点的工具。它的主要特点是可以重复使用,适合用于多线程分阶段处理任务的场景。在 Java 中,通过 CyclicBarrier,可以轻松实现多个线程在特定点同步,从而协调它们的执行顺序。