前言
CyclicBarrier
字面意思是循环栅栏,是一个同步的工具,能够允许一组线程去互相等待直到都到达了屏障,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();
}
}
运行结果:
总结
示意图:
CyclicBarrier
是借助ReentrantLock
加上Condition
等待唤醒的功能 进而实现的,在构建CyclicBarrier
时,传入的值会赋值给CyclicBarrier
内部维护count
变量,也会赋值给parties
变量(这是可以复用的关键)。
每次调用await
时,会将count -1
,操作count
值是直接使用ReentrantLock
来保证线程安全性。如果count
不为0,则添加则condition
队列中。如果count
等于0
时,则把节点从condition
队列添加至AQS
的队列中进行全部唤醒,并且将parties
的值重新赋值为count
的值(实现复用)。
完整代码已上传 Gitee Spring整合常用组件