JUC中的CyclicBarrier应用

88 阅读2分钟

CyclicBarrier

字面意思回环栅栏,通过它可以实现让一组线程等待至某个状态(屏障点)之后再全部同时执行。叫做回环是因为当所有等待线程都被释放以后,CyclicBarrier可以被重用。

public class CyclicBarrierTest {
    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(5, () -> {
            //可以进行汇总业务逻辑处理
            System.out.println("5个任务线程都到达了终点");
        });

        for (int i = 0; i < 20; i++) {
            new Thread(() -> {
                try {
                    Thread.sleep(new Random().nextInt(2000));
                    System.out.println("线程" + Thread.currentThread().getName() + "准备好了");
                    cyclicBarrier.await();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

执行结果:

线程Thread-14准备好了
线程Thread-8准备好了
线程Thread-3准备好了
线程Thread-7准备好了
线程Thread-0准备好了
5个任务线程都到达了终点
线程Thread-16准备好了
线程Thread-11准备好了
线程Thread-12准备好了
线程Thread-9准备好了
线程Thread-19准备好了
5个任务线程都到达了终点
线程Thread-4准备好了
线程Thread-2准备好了
线程Thread-5准备好了
线程Thread-13准备好了
线程Thread-1准备好了
5个任务线程都到达了终点
线程Thread-18准备好了
线程Thread-17准备好了
线程Thread-15准备好了
线程Thread-6准备好了
线程Thread-10准备好了
5个任务线程都到达了终点

CyclicBarrier与countDownLatch区别

  • CountDownLatch的计数器只能使用一次,而CyclicBarrier的计数器可以使用reset()

方法重置。所以CyclicBarrier能处理更为复杂的业务场景,比如如果计算发生错误,可

以重置计数器,并让线程们重新执行一次

  • CyclicBarrier还提供getNumberWaiting(可以获得CyclicBarrier阻塞的线程数量)、

isBroken(用来知道阻塞的线程是否被中断)等方法。

  • CountDownLatch会阻塞主线程,CyclicBarrier不会阻塞主线程,只会阻塞子线程。

  • CountDownLatch和CyclicBarrier都能够实现线程之间的等待,只不过它们侧重点

不同。CountDownLatch一般用于一个或多个线程,等待其他线程执行完任务后,再执

行。CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执

行。

  • CyclicBarrier 还可以提供一个 barrierAction,合并多线程计算结果。

  • CyclicBarrier是通过ReentrantLock的"独占锁"和Conditon来实现一组线程的阻塞

唤醒的,而CountDownLatch则是通过AQS的“共享锁”实现