文章目录
- 1. CyclicBarrier是什么
- 2 核心属性详解
- 3 核心方法详解
- 3.1 await()
- 3.1 breakBarrier()
- 4 总结
java 并发编程系列文章目录
1. CyclicBarrier是什么
在java的类注释上描述:一种同步辅助工具,允许一组线程都等待对方到达一个共同的障碍点。CyclicBarrier在涉及固定大小的线程组的程序中很有用,这些线程偶尔必须相互等待。屏障被称为循环的(Cyclic),因为它可以在等待线程释放后重新使用。
CyclicBarrier支持一个可选的Runnable命令,该命令在参与方中的最后一个线程到达之后,但在释放任何线程之前,每个屏障点运行一次。此屏障操作有助于在任何一方继续之前更新共享状态。
注:最后一个到达的线程负责执行runnable
示例在java的类注释中已经提供,可以复制粘贴运行看下
2 核心属性详解
private static class Generation {boolean broken = false;}//线程同步使用的锁private final ReentrantLock lock = new ReentrantLock();//等待的条件队列private final Condition trip = lock.newCondition();//线程同步等待的个数private final int parties;//全部达到点的执行的runnable任务private final Runnable barrierCommand;//标识private Generation generation = new Generation();//统计的数量字段private int count;
3 核心方法详解
3.1 await()
public int await() throws InterruptedException, BrokenBarrierException {try {return dowait(false, 0L);} catch (TimeoutException toe) {throw new Error(toe); // cannot happen}}//timed 是否是具有超时时间的阻塞,nanos超时时间private int dowait(boolean timed, long nanos)throws InterruptedException, BrokenBarrierException,TimeoutException {final ReentrantLock lock = this.lock;//先获取到锁lock.lock();try {final Generation g = generation;//如果当前g.broken == true 会抛出异常,这个变成true是栅栏被破坏,什么是破坏,下面可//以看到,执行逻辑下面会看到 //总结下:如果有线程被中断和runnable出现异常和超时时间已经到达没有和其他线程一起唤醒的会破坏这个栅栏if (g.broken)throw new BrokenBarrierException();//破坏条件1 线程被中断if (Thread.interrupted()) {breakBarrier();throw new InterruptedException();}//初始状态下count = parties;此时一个线程await 就减-1int index = --count;//最后一个线程await count == 0成立 会执行Runnable 执行完成。//会nextGeneration 就是唤醒所有的线程 重置count 和generationif (index == 0) { // trippedboolean ranAction = false;try {final Runnable command = barrierCommand;if (command != null)command.run();ranAction = true;nextGeneration();return 0;} finally {//破坏条件2 runable抛出异常 会执行breakBarrierif (!ranAction)breakBarrier();}}//此时是count != 0for (;;) {try {//如果不带超时时间的 直接await等待 带超时时间的 等待nanos时间if (!timed)trip.await();else if (nanos > 0L)nanos = trip.awaitNanos(nanos);} catch (InterruptedException ie) {//破坏条件3 如果等待的过程中线程被中断 执行 breakBarrierif (g == generation && ! g.broken) {breakBarrier();throw ie;} else {Thread.currentThread().interrupt();}}//如果一些线程正常await() 但是有一个线程执行了breakBarrier 此时唤醒线程//g.broken = true 所以其他线程被唤醒也会抛出该异常if (g.broken)throw new BrokenBarrierException();if (g != generation)return index;//破坏条件4 如果传入的nanos <= 0 会直接执行breakBarrier,一般在await(long //timeout, TimeUnit unit)里防止传入小于0if (timed && nanos <= 0L) {breakBarrier();throw new TimeoutException();}}} finally {lock.unlock();}}
3.1 breakBarrier()
private void breakBarrier() {//broken =true 让其他线程直接抛出异常generation.broken = true;//恢复count count = parties;//唤醒所有线程trip.signalAll();}
4 总结
CyclicBarrier在执行过程中有一个线程如果出现破坏栅栏情况,之后的其他线程的await方法都会抛出异常,CyclicBarrier可以平替CountDownLatch使用,CountDownLatch是使用AQS的公平锁实现,CyclicBarrier使用可重入锁ReentrantLock 实现,且可以支持一个runnable运行。可以通过合适的场景选用合适的类