1、什么是CyclicBarrier?
CyclicBarrier也叫同步屏障,在JDK1.5被引入,可以让一组线程达到一个屏障时被阻塞,直到最后一个线程达到屏障时,所以被阻塞的线程才能继续执行。
CyclicBarrier好比一扇门,默认情况下关闭状态,堵住了线程执行的道路,直到所有线程都就位,门才打开,让所有线程一起通过。(引于深入浅出java CyclicBarrier -- 战小狼,感觉这个比喻很好)
2、构造方法
默认构造函数 CyclicBarrier(int parties) parties阻塞线程数据
CyclicBarrier(int parties, Runnable barrierAction) parties 阻塞线程数据,barrierAction线程执行前先运行此runnable。
3、CyclicBarrier阻塞和运行示例
如果线程数达不到5,会一直等待或者是超时中断(await(时间))
以快递打包为例,5个货物为一箱,先将五个货物都拿到再进行打包,代码如下:
public static void main(String[] args) throws Exception{
/**
* CyclicBarrier 有两个构造方法 parties 总计数,runnable是 现在执行前先执行的方法
* CyclicBarrier barrier = new CyclicBarrier(5);
*/
CyclicBarrier barrier = new CyclicBarrier(5, () -> {
System.out.println("开始货物打包");
});
ExecutorService executorPool = Executors.newCachedThreadPool();
/**
* await提供了两个方法
* 1、await()
* 2、await(long timeout, TimeUnit unit) 超时写法,且需捕获异常 TimeOutException
*/
for (int i = 0; i < 11; i++) {
int num = i;
Thread.sleep(1000);
executorPool.execute(() -> {
try {
System.out.println(num + "号货物,已准备好,等待打包");
//barrier2.await(2, TimeUnit.SECONDS);
barrier.await();
System.out.println(num + "号货物,打包完成");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
});
}
executorPool.shutdown();
}
4、其他
①、isBroken()方法检测Barrier是否被破坏
②、await(long timeout, TimeUnit unit) 超时写法,且需捕获异常 TimeOutException
③、如果有线程已经处于等待状态,调用reset方法会导致已经在等待的线程出现BrokenBarrierException异常。并且由于出现了BrokenBarrierException,将会导致始终无法等待。
④、getNumberWaiting() 获取正在等待的线程数
5、CyclicBarrier的底层原理
CyclicBarrier类是concurrent并发包下的一工具类。
线程间同步阻塞是使用的是ReentrantLock,可重入锁
线程间通信使用的是Condition,Condition 将 Object 监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用。