CyclicBarrier使用及应用场景例子

CyclicBarrier是什么?

JDK1.5开始提供的并发编程,辅助工具类。用于并发编程的。

字面意思回环栅栏,通过它可以实现让一组线程等待至某个状态之后再全部同时执行。
叫做回环是因为当所有等待线程都被释放以后,CyclicBarrier可以被重用。
叫做栅栏,大概是描述所有线程被栅栏挡住了,当都达到时,一起跳过栅栏执行,也算形象。我们可以把这个状态就叫做barrier。

通过CyclicBarrier的await()方法,线程就处于barrier状态。

CyclicBarrier如何使用和工作?

看下API
CyclicBarrier有两个构造函数

public CyclicBarrier(int parties)
public CyclicBarrier(int parties, Runnable barrierAction)

第一个参数,表示那个一起执行的线程个数。
第二个参数,表示线程都处于barrier时,一起执行之前,先执行的一个线程。

让线程处于barrier状态的方法await()

public int await()
public int await(long timeout, TimeUnit unit)

第一个默认方法,表示要等到所有的线程都处于barrier状态,才一起执行
第二个方法,指定了等待的时间,当所有线程没有都处于barrier状态,又到了指定的时间,所在的线程就继续执行了。

CyclicBarrier应用场景例子

举个报旅行团旅行的例子。
出发时,导游会在机场收了护照和签证,办理集体出境手续,所以,要等大家都到齐才能出发,出发前再把护照和签证发到大家手里。
对应CyclicBarrier使用。
每个人到达后进入barrier状态。
都到达后,唤起大家一起出发去旅行。
旅行出发前,导游还会有个发护照和签证的动作。
代码如下:

/**
 * 旅行线程
 * Created by jiapeng on 2018/1/7.
 */
public class TravelTask implements Runnable{

    private CyclicBarrier cyclicBarrier;
    private String name;
    private int arriveTime;//赶到的时间

    public TravelTask(CyclicBarrier cyclicBarrier,String name,int arriveTime){
        this.cyclicBarrier = cyclicBarrier;
        this.name = name;
        this.arriveTime = arriveTime;
    }

    @Override
    public void run() {
        try {
            //模拟达到需要花的时间
            Thread.sleep(arriveTime * 1000);
            System.out.println(name +"到达集合点");
            cyclicBarrier.await();
            System.out.println(name +"开始旅行啦~~");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
}
/**
 * 导游线程,都到达目的地时,发放护照和签证
 * Created by jiapeng on 2018/1/7.
 */
public class TourGuideTask implements Runnable{

    @Override
    public void run() {
        System.out.println("****导游分发护照签证****");
        try {
            //模拟发护照签证需要2秒
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
/**
 * Created by jiapeng on 2018/1/7.
 */
public class Client {

    public static void main(String[] args) throws Exception{

        CyclicBarrier cyclicBarrier = new CyclicBarrier(3,new TourGuideTask());
        Executor executor = Executors.newFixedThreadPool(3);
        //登哥最大牌,到的最晚
        executor.execute(new TravelTask(cyclicBarrier,"哈登",5));
        executor.execute(new TravelTask(cyclicBarrier,"保罗",3));
        executor.execute(new TravelTask(cyclicBarrier,"戈登",1));
    }
}
执行结果
CyclicBarrier的底层原理

CyclicBarrier类是concurrent并发包下的一工具类。
线程间同步阻塞是使用的是ReentrantLock,可重入锁
线程间通信使用的是Condition,Condition 将 Object 监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用。

推荐阅读更多精彩内容