当前位置: 代码迷 >> 综合 >> JUC学习系列七(同步屏障 CyclicBarrier)
  详细解决方案

JUC学习系列七(同步屏障 CyclicBarrier)

热度:74   发布时间:2023-12-28 12:35:07.0

一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。

CyclicBarrier 支持一个可选的 Runnable 命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次。若在继续所有参与线程之前更新共享状态,此屏障操作 很有用。

public class Dragon {public void getBall(CyclicBarrier cb,int index){try {Thread.sleep(1000);System.out.println(Thread.currentThread().getName()+"获得"+index+"星龙珠!");cb.await();} catch ( Exception e) {e.printStackTrace();}}public static void main(String[] args) {final CyclicBarrier cb=new CyclicBarrier(7, new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+"集齐七颗龙珠召唤神龙!");}});final Dragon d=new Dragon();for (int i=1;i<8;i++){final int j=i;new Thread(new Runnable() {@Overridepublic void run() {d.getBall(cb,j);}}).start();}//检测重用性for (int i=1;i<8;i++){final int j=i;new Thread(new Runnable() {@Overridepublic void run() {
//                   int b= 8/(j-5);d.getBall(cb,j);}}).start();}}}

这个工具类使用起来比较简单。API中的异常破坏模式,内存一致性还没弄懂。后面在做补充吧!

源码剖析

结构:

我们在实例中new CyclicBarrier时,给它一个数目7和一个触发事件,在类中它们对应的就是parties和barrierCommand,如下:

这个类就只有一个await()常用。我们看看它的底层到底是是怎样一个流程吧!

 

 dowait()后面还有一个自旋方法,只要作用是当前线程阻塞时,检测它是否被打断等作用。感兴趣了可以自行阅读,比较简单。

 当前线程被打断时,或者中途抛出了异常在finally代码块里,调用的方法:

初始化以便复用的方法:

 以上就是其执行的原理。其中利用到了ReentrantLock。它自身也有一个count的int类型数值做计数器,跟AQS的思想很相近,当这个count减为0的时候,触发构造器里的线程任务类。每次调用await()方法,会使这个count计数器减一。中间也考虑到线程打断等情况,掺杂了相关的处理。源码还是很容易理解的。

  相关解决方案