CyclicBarrier 的使用

简介: CyclicBarrier 的使用

CyclicBarrier使用场景


用于协调多个线程同步执行操作的场合,所有线程等待完成,然后一起做事情( 相互之间都准备好,然后一起做事情 )

例如百米赛跑,必须等待所有运动员都准备好了,才能比赛。

运动员准备好,裁判也准备好,才能开始正式比赛。


例子


 

CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
        new Thread(() -> {
            try {
                Thread.sleep(1000);
                System.out.println("t1 在准备 ");
                cyclicBarrier.await();   // 等另外一个线程准备好 然后开始做事情
                System.out.println("t1 准备好了  ");
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
        }).start();
        new Thread(() -> {
            try {
                Thread.sleep(2000);
                System.out.println("t2 在准备  ");
                cyclicBarrier.await(); // 等另外一个线程准备好 然后开始做事情
                System.out.println("t2 准备好了  ");
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
        }).start();
        
        System.out.println(" 裁判 在准备 ");
        try {
            cyclicBarrier.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
        System.out.println(" 裁判 准备好了 ");
        while (true){
            if (cyclicBarrier.getNumberWaiting()==0){
                System.out.println(" 时间到: 开始比赛");
                return;
            }
        }

 

关于CyclicBarrier的底层执行流程总结:

  • 1、初始化CyclicBarrier中的各种成员变量,包括parties、count以及Runnable(可选);
  • 2、当调用await()方法时,底层会先检查计数器是否已经归零,如果是的话,那么就首先执行可选的Runnable,接下来开始下一个generation;(注意:这里只是调用Runnable的run()方法,并不是调用start()方法开启另一个线程)
  • 3、在下一个分代中,将会重置count值为parties,并且创建新的Generation实例;
  • 4、同时会调用Condition的singalAll方法,唤醒所有在屏障前面等待的线程,让其开始继续执行;(注意:当有可选的Runnable时,是执行完run()方法中的汇总操作,其他线程才会继续执行)
  • 5、如果计数器没有归零,那么当前的调用线程将会通过Condition的await方法,在屏障前进行等待;
  • 6、以上所有执行流程均在lock锁的控制范围内,不会出现并发情况。
  • 7、在下一个分代时,该屏障又可以继续使用,例如计数器是3,线程1,线程2和线程3冲破了当前屏障后,下一个分代的屏障可以去给线程4,线程5和线程6使用,也可以又给线程1,线程2和线程3使用(自己总结的)
CyclicBarrier cyclicBarrier = new CyclicBarrier(2, new Runnable() {
            @Override
            public void run() {
                System.out.println("汇总 然后继续执行没有执行的部分");
            }
        });

CountDownLatch是基于AQS实现的;而CyclicBarrier是基于ReentrantLock重入锁实现的,当然ReentrantLock也是基于AQS实现的,非要说CyclicBarrier也是基于AQS实现的也不为过。

await()方法有两层含义:

1、先检查前面是否已经有count个线程了,如果没有线程则会进入等待状态

2、当检测到屏障已经有count个线程了,则所有线程会冲出屏障继续执行(如果有Runnable参数的构造方法先执行汇总方法)


目录
相关文章
|
6月前
|
Java 测试技术
CountDownLatch、CyclicBarrier让线程听我号令
CountDownLatch、CyclicBarrier让线程听我号令
67 0
|
6月前
|
设计模式 Java
CountDownLatch和CyclicBarrier源码详解
我现在有个场景:现在我有50个任务,这50个任务在完成之后,才能执行下一个函数,要是你,你怎么设计?可以用JDK给我们提供的线程工具类,CountDownLatch和CyclicBarrier都可以完成这个需求。基于AQS实现,会将构造CountDownLatch的入参传递至statecountDown()就是在利用CAS将state减1,await)实际就是让头节点一直在等待state为0时,释放所有等待的线程。
68 1
|
Java BI
CountDownLatch,CyclicBarrier,Semaphore
在开发过程中我们常常遇到需要对多个任务进行汇总,比如报表,或者大屏显示,需要将所有接口的数据都 获取到后再进行汇总,如果使用同步的方式,那么会比较耗时,体验不好,所以我们使用多线程,但是使用多线程 只能异步的执行,有些接口响应比较快,有些比较慢,而返回结果之间又有依赖,这样就无法汇总了, 所以我们引入了CountDownLatch,它能让所有子线程全部执行完毕后主线程才会往下执行,如果子线程没有执行完毕 ,那么主线程将无法继续向下执行。
62 0
|
6月前
CountDownLatch和CyclicBarrier你使用过吗?
CountDownLatch和CyclicBarrier你使用过吗?
40 0
|
3月前
|
Java
CountDownLatch、CyclicBarrier 使用区别
CountDownLatch、CyclicBarrier 使用区别
30 1
|
12月前
CountDownLatch和CyclicBarrier的区别
CountDownLatch和CyclicBarrier的区别
34 0
CyclicBarrier 使用详解
本文主要对CyclicBarrier的相关知识点进行了介绍和讲解
155 0
CountDownLatch&CyclicBarrier&Semaphore
本文将介绍一下CountDownLatch 、 CyclicBarrier 、 Semaphore这几个控制线程的类。
 CountDownLatch&CyclicBarrier&Semaphore
|
消息中间件
CountDownLatch&CyclicBarrier
CountDownLatch&CyclicBarrier
138 0
CountDownLatch&CyclicBarrier