Java 标准库 API 系列之 CyclicBarrier

本贴最后更新于 332 天前,其中的信息可能已经时移世易

CyclicBarrier 也是 Java 中的一个同步工具类,它允许一组线程等待彼此达到一个共同的屏障点,直到所有线程都到达屏障点后才能继续执行。CyclicBarrier 可以被认为是一个可重用的计数器,每当一个线程到达屏障点时,计数器减 1,当计数器减为 0 时,表示所有线程都已到达屏障点,等待的线程可以继续执行。

API

CyclicBarrier 的常用方法有两个:

  • int await():表示一个线程已经到达屏障点,等待其他线程,如果所有线程都到达屏障点,则计数器重置,并且所有线程都继续执行;
  • int await(long timeout, TimeUnit unit):表示一个线程已经到达屏障点,等待其他线程,如果所有线程都到达屏障点,则计数器重置,并且所有线程都继续执行;如果超时则抛出 TimeoutException 异常。

以下是一个使用 CyclicBarrier 进行线程同步的示例代码:

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

public class CyclicBarrierExample {
    private static CyclicBarrier barrier = new CyclicBarrier(3);

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            System.out.println("Task 1 is running");
            try {
                barrier.await();
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
            System.out.println("Task 1 is completed");
        });

        Thread t2 = new Thread(() -> {
            System.out.println("Task 2 is running");
            try {
                barrier.await();
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
            System.out.println("Task 2 is completed");
        });

        Thread t3 = new Thread(() -> {
            System.out.println("Task 3 is running");
            try {
                barrier.await();
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
            System.out.println("Task 3 is completed");
        });

        t1.start();
        t2.start();
        t3.start();

        Thread.sleep(1000);

        System.out.println("All tasks are started");

        t1.join();
        t2.join();
        t3.join();

        System.out.println("All tasks are completed");
    }
}

可重用表现在哪?

CyclicBarrier 是可重用的,表现在以下两个方面:

  1. 计数器重置:当所有线程都到达屏障点后,计数器会被重置为初始值,即 CyclicBarrier 对象创建时传入的值,这样 CyclicBarrier 可以被用于多个屏障同步。在上述示例代码中,barrier 变量在初始化时传入的是 3,表示需要等待 3 个线程到达屏障点,如果需要再次使用该 CyclicBarrier 对象进行同步,只需调用 barrier.reset() 方法将计数器重置为 3 即可。
  2. 异常处理:如果一个线程在等待其他线程时被中断或超时,则 CyclicBarrier 会抛出 BrokenBarrierExceptionTimeoutException 异常,这样可以对异常进行处理后继续使用 CyclicBarrier 进行同步。在上述示例代码中,await() 方法可能会抛出 BrokenBarrierException 异常,因此在调用 await() 方法时需要进行异常处理。

CyclicBarrier 和 CountDownLatch 的区别是什么?

之前我们介绍了 CountDownLatch,似乎他们两个的作用是相同的,其实不然。

功能不同

CountDownLatch 被作用于线程等待其他线程完成,然后被阻塞的线程才继续执行,而 CyclicBarrier 通常用于将多个线程的执行阶段进行同步,以便它们可以在栅栏位置进行等待,直到所有线程都达到栅栏位置,然后所有线程可以同时执行后续操作。

重用能力不同

CyclicBarrier 可以被重用。一旦所有线程都到达栅栏位置并且栅栏被打破,它会自动重置,可以再次使用。

CountDownLatch 不能被重用。一旦计数器达到零并且门闩被打开,它不能再次使用

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3168 引用 • 8207 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...