CyclicBarrier:人齐了,老司机就发车了!(3)

简介: CyclicBarrier:人齐了,老司机就发车了!(3)

以上代码执行结果如下:


微信图片_20220120172641.jpg


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


实现原理


我们先来看下 CyclicBarrier 的类图:


微信图片_20220120173424.jpg


由上图可知 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。



相关文章
|
5月前
|
安全 Java 程序员
惊呆了!Java多线程里的“synchronized”竟然这么神奇!
【6月更文挑战第20天】Java的`synchronized`关键字是解决线程安全的关键,它确保同一时间只有一个线程访问同步代码。在案例中,`Counter`类的`increment`方法如果不加同步,可能会导致竞态条件。通过使用`synchronized`方法或语句块,可以防止这种情况,确保线程安全。虽然同步会带来性能影响,但它是构建并发应用的重要工具,平衡同步与性能是使用时需考虑的。了解并恰当使用`synchronized`,能有效应对多线程挑战。
20 1
|
5月前
|
存储 并行计算 监控
为师妹写的《Java并发编程之线程池十八问》被表扬啦!
【6月更文挑战第5天】为师妹写的《Java并发编程之线程池十八问》被表扬啦!
56 7
|
5月前
|
存储 缓存 Java
老程序员分享:Java并发编程:线程池的使用
老程序员分享:Java并发编程:线程池的使用
|
5月前
|
Java
惊呆了!原来JAVA多线程间是这样“窃窃私语”的!
【6月更文挑战第20天】在Java中,多线程通过wait()和notify()/notifyAll()进行通信,确保共享数据的同步。例如,一个生产者线程在队列满时等待,消费者线程在队列空时等待。当条件改变时,一个线程使用notify()唤醒另一个等待的线程,保证数据的一致性。这种“窃窃私语”机制是Java实现线程协作的关键。
40 0
|
监控 Java
带着面试官畅游Java线程池
java中经常需要用到多线程来处理一些业务,如果单纯使用继承Thread或者实现Runnable接口的方式来创建线程,那样势必有创建及销毁线程耗费资源、线程上下文切换问题。同时创建过多的线程也可能引发资源耗尽的风险,这个时候引入线程池比较合理,方便线程任务的管理。
带着面试官畅游Java线程池
CyclicBarrier:人齐了,老司机就发车了!(1)
CyclicBarrier:人齐了,老司机就发车了!(1)
140 0
CyclicBarrier:人齐了,老司机就发车了!(1)
CyclicBarrier:人齐了,老司机就发车了!(2)
CyclicBarrier:人齐了,老司机就发车了!(2)
126 0
CyclicBarrier:人齐了,老司机就发车了!(2)
|
缓存 Java
面试官因为线程池,让我出门左拐!
前几天阿粉的朋友面试,在面试的时候,面试官问到了框架,项目,JVM还有一些关于线程池的内容,而这个线程池,让阿粉的朋友分分钟被面试官吊打,只能出门左拐,地铁站回家了。为什么呢?因为线程池他是真的没有下功夫去准备,只能凉凉了。
面试官因为线程池,让我出门左拐!
|
Cloud Native Java 大数据
放假了再撸一篇:StampedLock(建议收藏)
相信大部分小伙伴都放假了吧,冰河曾经说过:假期是超越他人的最好时机,悄悄努力,然后惊艳所有人。
141 0
放假了再撸一篇:StampedLock(建议收藏)
|
Java
腾讯面试居然跟我扯了半小时的CountDownLatch
一个长头发、穿着清爽的小姐姐,拿着一个崭新的Mac笔记本向我走来,看着来势汹汹,我心想着肯定是技术大佬吧!但是我也是一个才华横溢的人,稳住我们能赢。
159 0
腾讯面试居然跟我扯了半小时的CountDownLatch