CyclicBarrier介绍

字面意思回环栅栏(循环屏障),通过它可以实现让一组线程等待至某个状态(屏障点)之后再全部同时执行。叫做回环是因为当所有等待线程都被释放以后,CyclicBarrier可以被重用。

CyclicBarrier的使用
构造方法
1 // parties 表示屏障拦截的线程数量,每个线程调用 await 方法告诉 CyclicBarrier 我已经
到达了屏障,然后当前线程被阻塞。
2 public CyclicBarrier ( int parties )
3 // 用于在线程到达屏障时,优先执行 barrierAction ,方便处理更复杂的业务场景 ( 该线程的
执行时机是在到达屏障之后再执行 )
4 public CyclicBarrier ( int parties , Runnable barrierAction )
重要方法
1 // 屏障 指定数量的线程全部调用 await() 方法时,这些线程不再阻塞
2 // BrokenBarrierException 表示栅栏已经被破坏,破坏的原因可能是其中一个线程 await()
时被中断或者超时
3 public int await () throws InterruptedException , BrokenBarrierException
4 public int await ( long timeout , TimeUnit unit ) throws InterruptedException , Bro
kenBarrierException , TimeoutException
5
6 // 循环 通过 reset() 方法可以进行重置
7 public void reset ()
CyclicBarrier应用场景
CyclicBarrier 可以用于多线程计算数据,最后合并计算结果的场景。
1 public class CyclicBarrierTest2 {
2
3 // 保存每个学生的平均成绩
4 private ConcurrentHashMap < String , Integer > map = new ConcurrentHashMap < String , I
nteger > ();
5
6 private ExecutorService threadPool = Executors . newFixedThreadPool ( 3 );
7 8 private CyclicBarrier cb = new CyclicBarrier ( 3 ,() ‐> {
9 int result = 0 ;
10 Set < String > set = map . keySet ();
11 for ( String s : set ){
12 result += map . get ( s );
13 }
14 System . out . println ( " 三人平均成绩为 :" + ( result / 3 ) + " " );
15 });
16
17
18 public void count (){
19 for ( int i = 0 ; i < 3 ; i ++ ){
20 threadPool . execute ( new Runnable (){
21
22 @Override
23 public void run () {
24 // 获取学生平均成绩
25 int score = ( int )( Math . random () * 40 + 60 );
26 map . put ( Thread . currentThread (). getName (), score );
27 System . out . println ( Thread . currentThread (). getName ()
28 + " 同学的平均成绩为: " + score );
29 try {
30 // 执行完运行 await(), 等待所有学生平均成绩都计算完毕
31 cb . await ();
32 } catch ( InterruptedException | BrokenBarrierException e ) {
33 e . printStackTrace ();
34 }
35 }
36
37 });
38 }
39 }
40
41 public static void main ( String [] args ) {
42 CyclicBarrierTest2 cb = new CyclicBarrierTest2 ();
43 cb . count ();
44 }
45 }
利用CyclicBarrier的计数器能够重置,屏障可以重复使用的特性,可以支持类似“人满发车”的
场景
1 public class CyclicBarrierTest3 {
2
3 public static void main ( String [] args ) { 4
5 AtomicInteger counter = new AtomicInteger ();
6 ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor (
7 5 , 5 , 1000 , TimeUnit . SECONDS ,
8 new ArrayBlockingQueue <> ( 100 ),
9 ( r ) ‐> new Thread ( r , counter . addAndGet ( 1 ) + " " ),
10 new ThreadPoolExecutor . AbortPolicy ());
11
12 CyclicBarrier cyclicBarrier = new CyclicBarrier ( 5 ,
13 () ‐> System . out . println ( " 裁判:比赛开始 ~~" ));
14
15 for ( int i = 0 ; i < 10 ; i ++ ) {
16 threadPoolExecutor . submit ( new Runner ( cyclicBarrier ));
17 }
18
19 }
20 static class Runner extends Thread {
21 private CyclicBarrier cyclicBarrier ;
22 public Runner ( CyclicBarrier cyclicBarrier ) {
23 this . cyclicBarrier = cyclicBarrier ;
24 }
25
26 @Override
27 public void run () {
28 try {
29 int sleepMills = ThreadLocalRandom . current (). nextInt ( 1000 );
30 Thread . sleep ( sleepMills );
31 System . out . println ( Thread . currentThread (). getName () + " 选手已就位 , 准备共用
时: " + sleepMills + "ms" + cyclicBarrier . getNumberWaiting ());
32 cyclicBarrier . await ();
33
34 } catch ( InterruptedException e ) {
35 e . printStackTrace ();
36 } catch ( BrokenBarrierException e ){
37 e . printStackTrace ();
38 }
39 }
40 }
41
42 }
CyclicBarrier与CountDownLatch的区别
7. CountDownLatch的计数器只能使用一次,而CyclicBarrier的计数器可以使用reset() 方
法重置。 所以CyclicBarrier能处理更为复杂的业务场景,比如如果计算发生错误,可以重
置计数器,并让线程们重新执行一次
8. CyclicBarrier还提供getNumberWaiting(可以获得CyclicBarrier阻塞的线程数量)、
isBroken(用来知道阻塞的线程是否被中断)等方法。
9. CountDownLatch会阻塞主线程,CyclicBarrier不会阻塞主线程,只会阻塞子线程。
10. CountDownLatch和CyclicBarrier都能够实现线程之间的等待,只不过它们侧重点不
同。CountDownLatch一般用于一个或多个线程,等待其他线程执行完任务后,再执行。
CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行。
11. CyclicBarrier 还可以提供一个 barrierAction,合并多线程计算结果。
12. CyclicBarrier是通过ReentrantLock的"独占锁"和Conditon来实现一组线程的阻塞唤
醒的,而CountDownLatch则是通过AQS的“共享锁”实现

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值