Java JUC并发包之CyclicBarrier循环栅栏

时间:2023-01-19 08:57:50


不问收获,只问耕耘 ????????????

文章目录

  • ​​前言​​
  • ​​代码示例​​
  • ​​总结​​

前言

​CyclicBarrier​​ 字面意思是循环栅栏,是一个同步的工具,能够允许一组线程去互相等待直到都到达了屏障,CyclicBarrier对于涉及到固定大小的线程是非常有用的,线程们必须相互等待。该屏障称之为循环屏障,是因为当等待屏障的线程被释放之后,该屏障能循环使用。

什么意思呢?假如有五个探险者去探险,在他们前方有三道门,每道门都需要五个人同时发力召唤神龙才能打开,如果有一个人走的特别快,它先到达了门前,但是它一个人打不开门,需要五个人同时抵达才能打开门,所以走的快的只能等待最慢的达到,一组五个人到齐之后才能执行打开门这个动作。

Java JUC并发包之CyclicBarrier循环栅栏

Java JUC并发包之CyclicBarrier循环栅栏

Java JUC并发包之CyclicBarrier循环栅栏

Java JUC并发包之CyclicBarrier循环栅栏

代码示例

模拟五个人过门的案例

@GetMapping(value = "/cyclicBarrier")
public void cyclicBarrier() {
// 参与的线程数
int threadNum = 5;
//创建cyclicBarrier实例,定义barrierAction
CyclicBarrier cyclicBarrier = new CyclicBarrier(5, () ->
System.out.println("已到全部通过栅栏")
);
//创建线程开始执行
for (int i = 1; i <= threadNum; i++) {
new Thread(() -> {
for (int j = 1; j <= 3; j++) {
try {
Random rand = new Random();
//随机一个2-5的整数
int randomNum = rand.nextInt(4) + 2;
Thread.sleep(randomNum * 1000);
System.out.println(Thread.currentThread().getName() + ", 通过了第" + j +
"道栅栏, " +
"使用了 " + randomNum + "s");
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}, "thread--" + i).start();
}
}

运行结果:

Java JUC并发包之CyclicBarrier循环栅栏

总结

示意图:

Java JUC并发包之CyclicBarrier循环栅栏

​CyclicBarrier​​​是借助​​ReentrantLock​​​加上​​Condition​​​ 等待唤醒的功能 进而实现的,在构建​​CyclicBarrier​​​时,传入的值会赋值给​​CyclicBarrier​​​内部维护​​count​​​变量,也会赋值给​​parties​​变量(这是可以复用的关键)。

每次调用​​await​​​时,会将​​count -1​​​ ,操作​​count​​​值是直接使用​​ReentrantLock​​​来保证线程安全性。如果​​count​​​不为0,则添加则​​condition​​​队列中。如果​​count​​​等于​​0​​​时,则把节点从​​condition​​​队列添加至​​AQS​​​的队列中进行全部唤醒,并且将​​parties​​​的值重新赋值为​​count​​的值(实现复用)。


完整代码已上传 ​​Gitee Spring整合常用组件​

到此,本章内容就介绍完啦