Java并发之CyclicBarrier

Posted by Kaka Blog on July 17, 2019

CyclicBarrier介绍

作用

它允许一组线程相互等待,直到到达某个公共屏障点。

业务场景

CyclicBarrier主要是实现了多个线程之间相互等待,直到所有的线程都满足了条件之后各自才能继续执行后续的操作,描述的多个线程内部相互等待的关系。

使用

  • 初始化:用一个给定的计数器来初始化。
  • await():调用await方法的线程会一直处于阻塞状态,且计数器加1,当计数器的值达到设置的初始值时,所有因调用await进入等待状态的线程被唤醒,继续执行后续操作。

CyclicBarrier 与 CountDownLatch 区别

  • CountDownLatch 是一次性的,CyclicBarrier 是可循环利用的
  • CountDownLatch 参与的线程的职责是不一样的,有的在倒计时,有的在等待倒计时结束。CyclicBarrier 参与的线程职责是一样的。

例子

import java.util.concurrent.CyclicBarrier;

class FooBar {
    private int n;
    private CyclicBarrier barrier = new CyclicBarrier(2);
    private volatile int num = 0;

    public FooBar(int n) {
        this.n = n;
    }

    public void foo(Runnable printFoo) throws InterruptedException {
        
        for (int i = 0; i < n; i++) {
            try {
                barrier.await();
            } catch (Exception e) {
                e.printStackTrace();
            }
        	// printFoo.run() outputs "foo". Do not change or remove this line.
            while(num != 0) {}
        	printFoo.run();
            num = 1;
        }
    }

    public void bar(Runnable printBar) throws InterruptedException {
        
        for (int i = 0; i < n; i++) {
            try {
                barrier.await();
            } catch (Exception e) {
                e.printStackTrace();
            }
            // printBar.run() outputs "bar". Do not change or remove this line.
            while (num != 1) {}
        	printBar.run();
            num = 0;
        }
    }
}

效果:两个不同的线程将会共用一个 FooBar 实例。其中一个线程将会调用 foo() 方法,另一个线程将会调用 bar() 方法,以确保 “foobar” 被输出 n 次。

参考