CyclicBarrier:人齐了,老司机就可以发车了! (2)

以上代码执行结果如下:

image.png


从上述结果可以看出:当 CyclicBarrier 的计数器设置为 2 时,线程 2 和 线程 3 都到屏障点之后,老司机才会发第一波车,再 2s 之后,线程 1 和线程 4 也同时进入了屏障点,这时候老司机又可以再发一波车了。

实现原理

我们先来看下 CyclicBarrier 的类图:

image.png


由上图可知 CyclicBarrier 是基于独占锁 ReentrantLock 实现的,其底层也是基于 AQS 的。

在 CyclicBarrier 类的内部有一个计数器 count,当 count 不为 0 时,每个线程在到达屏障点会先调用 await 方法将自己阻塞,此时计数器会减 1,直到计数器减为 0 的时候,所有因调用 await 方法而被阻塞的线程就会被唤醒继续执行。当 count 计数器变成 0 之后,就会进入下一轮阻塞,此时 parties(parties 是在 new CyclicBarrier(parties) 时设置的值)会将它的值赋值给 count 从而实现复用。

常用方法

CyclicBarrier(parties):初始化相互等待的线程数量的构造方法。

CyclicBarrier(parties,Runnable barrierAction):初始化相互等待的线程数量以及屏障线程的构造方法,当 CyclicBarrier 的计数器变为 0 时,会执行 barrierAction 构造方法。

getParties():获取 CyclicBarrier 打开屏障的线程数量,也称为方数。

getNumberWaiting():获取正在CyclicBarrier上等待的线程数量。

await():在 CyclicBarrier 上进行阻塞等待,直到发生以下情形之一:
在 CyclicBarrier 上等待的线程数量达到 parties,则所有线程被释放,继续执行;

当前线程被中断,则抛出 InterruptedException 异常,并停止等待,继续执行;

其他等待的线程被中断,则当前线程抛出 BrokenBarrierException 异常,并停止等待,继续执行;

其他等待的线程超时,则当前线程抛出 BrokenBarrierException 异常,并停止等待,继续执行;

其他线程调用 CyclicBarrier.reset() 方法,则当前线程抛出 BrokenBarrierException 异常,并停止等待,继续执行。

await(timeout,TimeUnit):在CyclicBarrier上进行限时的阻塞等待,直到发生以下情形之一:

在 CyclicBarrier 上等待的线程数量达到 parties,则所有线程被释放,继续执行;

当前线程被中断,则抛出 InterruptedException 异常,并停止等待,继续执行;

当前线程等待超时,则抛出 TimeoutException 异常,并停止等待,继续执行;

其他等待的线程被中断,则当前线程抛出 BrokenBarrierException 异常,并停止等待,继续执行;

其他等待的线程超时,则当前线程抛出 BrokenBarrierException 异常,并停止等待,继续执行;

其他线程调用 CyclicBarrier.reset() 方法,则当前线程抛出 BrokenBarrierException 异常,并停止等待,继续执行。

isBroken():获取是否破损标志位 broken 的值,此值有以下几种情况:

CyclicBarrier 初始化时,broken=false,表示屏障未破损;

如果正在等待的线程被中断,则 broken=true,表示屏障破损;

如果正在等待的线程超时,则 broken=true,表示屏障破损;

如果有线程调用 CyclicBarrier.reset() 方法,则 broken=false,表示屏障回到未破损状态。

reset():使得CyclicBarrier回归初始状态,直观来看它做了两件事:

如果有正在等待的线程,则会抛出 BrokenBarrierException 异常,且这些线程停止等待,继续执行。

将是否破损标志位 broken 置为 false。

总结

CyclicBrrier 是通过独占锁 ReentrantLock 实现计数器的原子性更新的,CyclicBrrier 最常用的是 await() 方法,使用此方法会将计数器 -1,并判断当前的计数器是否为 0,如果不为 0 就会阻塞等待,并计时器为 0 之后,才能继续执行剩余任务。CyclicBrrier 相比于 CountDownLatch 来说,它的优势在于可以重复使用。

参考 & 鸣谢

blog.csdn.net/qq_39241239/article/details/87030142
blog.csdn.net/zzg1229059735/article/details/61191679

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsswyj.html