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 实现组合使用。