1.CyclicBarrier的思想
CyclicBarrier的思想在我们生活中就可以找到,我们就以火车道口拦杆为例:
我们先看一下,没有火车道口拦杆时的情形:

但是,正如一句老话说的好,没有约束的自由总是危险的。
想象一下,这时候,火车突然来了。。。

这时候,恐怕就出现了这种场景,一场人间生死离别的惨祸

有约束的自由才是真正的自由:

我们知道火车道口拦杆的作用:为了让行人规避火车,在火车运行的时候,铁路人员把拦杆放下,这样所有的行人都不能通过了。只有到拦杆处聚集了一拨人的时候,才会统一把拦杆打开,让所有人一次通过。而之后来的人,只有等到下一次拦杆打开才能通过。并且,等待在同一个拦杆处的人,不管你来的是早是晚,你都要先等待。只有等拦杆打开之后,你们这一组人才能同时通过。并不是说,谁先来谁先通过。我们通过这个拦杆可以控制让一批人同时通过。
CyclicBarrier就类似于一个火车道口拦杆。我们想通过CyclicBarrier来实现一个同步控制,可以把每一个cyclicBarrier理解成一个火车道口拦杆。
2.CyclicBarrier的作用
而JUC包下的cyclicBarrier的作用也是这样,它同样实现的也是一个同步控制。它可以对一组线程进行协同。同一个CyclicBarrier下的所有线程一旦到达了拦杆处,它就必须等待,只有等到所有线程都到达了公共屏障点处,才能继续运行。
CyclicBarrier是一个同步辅助器。 通俗点讲就是:让一组线程到达一个屏障时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活。
3.CyclicBarrier的理解
我们可以看到CyclicBarrier的内部是使用重入锁ReentrantLock和Condition。它有两个构造函数:
CyclicBarrier(int parties):创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,但它不会在启动 barrier 时执行预定义的操作。
CyclicBarrier(int parties, Runnable barrierAction) :创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,并在启动 barrier 时执行 给定的屏障操作,该操作由最后一个进入 barrier 的线程执行。
parties表示拦截线程的数量,这里的parties就是起到一个计数器的作用。parties规定了到达屏障处的线程个数。只有当规定数量的线程都到达了公共屏障点时,才会放行。
关键点
理解CyclicBarrier的关键是要理解: await()方法 和parties 构造参数。
parties参数就是一个倒计时计数器,它被初始化为一个值N,只有N的值为减为0时即:所有的线程都达到了公共屏障点时,才会放行所有等待在拦杆处线程,让它们能继续往下运行。
而每当有一个线程调用await()方法就意味着有一个线程到达了公共屏障点cyclicBarrier。这时,parties的值减1。
4.代码案例
需求: 只有当三个线程都同时到达拦杆处时,才放行。
下面这个小案例就简单说明了CyclicBarrier的使用。

最后,贴上完整的代码:
public class CyclicBarrierTest {
private static CyclicBarrier cyclicBarrier;
/**
* 问题:cyclicBarrier的await方法的作用是什么???
* 在什么时候调用yclicBarrier.await()方法
* cyclicBarrier = new CyclicBarrier(5, new Runnable());
* 构造方法中的5的作用,cyclicBarrier的实现逻辑是不是就是5和await的结合实现。
*
* @param args
*/
//关键点: 有一个线程调用await()方法就意味着有一个线程到达了cyclicBarrier
//关键词: 公共屏障点 commont barrier point
//CyclicBarrier的两个构造函数
//parties表示拦截线程的数量。
//CyclicBarrier(int parties)
//当所有线程都已经到达barrier处(index == 0),
//则会通过nextGeneration()进行更新换地操作,在这个步骤中,做了三件事:唤醒所有线程,重置count,generation。
//这里面的parties就是起到一个计数器的作用
static class CyclicBarrierThread extends Thread{
public void run() {
//System.out.println(Thread.currentThread().getName() + "到了");
//等待
try {
//执行一些其他逻辑
//do something before reaching barrier
System.out.println(Thread.currentThread().getName()+"正在来的路上");
System.out.println(Thread.currentThread().getName()+"到达了拦杆处");
cyclicBarrier.await();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
//只有3个人都到齐时,才开会
//人都到齐之后,执行Runnable中的动作
cyclicBarrier=new CyclicBarrier(3, new Runnable() {
@Override
public void run() {
System.out.println("所有线程都已到达拦杆处,现在把拦杆打开了,大家都通过吧");
}
});
//开启3个线程
for (int i = 0; i < 3; i++) {
//创建3个线程
Thread t=new CyclicBarrierThread();
t.setName("线程Thread_"+i);
t.start();
}
}
}