扫描下方二维码或者微信搜索公众号
菜鸟飞呀飞
,即可关注微信公众号,阅读更多Spring源码分析
和Java并发编程
文章。
上一篇文章介绍了工具类
CountDownLatch
的原理和使用场景(并发工具类CountDownLatch的源码分析以及使用场景),今天将介绍JUC包下另一个十分常用的并发工具类CyclicBarrier
,翻译过来就是可循环
使用的屏障
。
简介
- CyclicBarrier的功能与CountDownLatch的功能十分类似,也是
控制线程的执行顺序
,但是它与CountDownLatch的区别是,CyclicBarrier是让一组线程阻塞在同一屏障(同步点)处,直到最后一个线程到达屏障(也就是屏障的计数器减为0),屏障才会打开,这些阻塞在屏障处的线程才会继续往下执行。CountDownLatch是让一组或者一个线程等待其他线程执行完后,当前线程才继续执行。另外一点区别就是,CyclicBarrier的计数器减为0后,可以重置计数器,从而可以再次使用,这一点通过类名中含有Cyclic
(循环)就能看出。而CountDownLatch的计数器减为0后,不会重置,因此不能重复使用。
示例
- CyclicBarrier的使用也十分简单,只需要new一个CyclicBarrier创建一个实例对象,它的构造方法中需要传入一个
int类型
的参数,用来指定屏障的大小
(即当多少个线程到达屏障后,屏障打开),然后在线程中调用await()
方法即可让线程阻塞在屏障处。 - 如下Demo示例中,通过10个线程模拟了十个短跑运动员。在现实生活中,100米赛跑的时候,运动员需要听到发令枪响之后才能起跑,所有运动员的起跑时间是在同一个时间的,不能抢跑。发令枪就相当于程序中的CyclicBarrier,当所有人准备好,听到发令枪响(达到屏障)时,才能开始起跑。
public class CyclicBarrierDemo {
public static void main(String[] args) {
Random random = new Random();
CyclicBarrier cyclicBarrier = new CyclicBarrier(10);
List<Thread> threads = new ArrayList<>(10);
for (int i = 0; i < 10; i++) {
threads.add(new Thread(()->{
int time = random.nextInt(5) + 1;
try {
// 通过线程休眠来模拟每位运动员的准备时间
Thread.sleep(time * 1000);
System.out.println(Thread.currentThread().getName() + "准备就绪");
// 运动员准备就绪后,就示意发令员自己准备好了,即调用await()方法
cyclicBarrier.await();
System.out.println("起跑枪响,"+Thread.currentThread().getName() + "起跑");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e)