CyclicBarrier 用法详解

91 阅读1分钟

CyclicBarrier 用法详解

CyclicBarrier使用场景

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

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

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


       CyclicBarrier cyclicBarrier = new CyclicBarrier(3);


        new Thread(() -> {
            try {
                Thread.sleep(10_000);
                System.out.println("t1 在准备 ");
                cyclicBarrier.await();   // 等另外一个一个线程准备好 然后开始做事情
                System.out.println("t1 准备好了  ");
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }

        }).start();

        new Thread(() -> {
            try {
                Thread.sleep(5_000);
                System.out.println("t2 在准备  ");
                cyclicBarrier.await(); // 等另外一个一个线程准备好 然后开始做事情
                System.out.println("t2 准备好了  ");
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
        }).start();


        System.out.println(" 裁判 在准备 ");
        cyclicBarrier.await();
        System.out.println(" 裁判 准备好了 ");


        while (true){
            if (cyclicBarrier.getNumberWaiting()==0){
                System.out.println(" 时间到: 开始比赛");
                return;
            }
        }


    }

如下图,当裁判准备好,运动员也准备好,才能开始比赛。
在这里插入图片描述

但是如果运动员有的没到场,那就是缺席,也可以比赛,这里就需要使用 Phaser 这个工具类比CyclicBarrier和``都强大

如果任务在指定时间内,运行没结束,CyclicBarrier还可以重新运行

  cyclicBarrier.reset();  // 可以重新执行

在等待的过程中,如果一个已经结束,另一个还在等待,此时reset会抛出异常,另一个被迫打断

    CyclicBarrier cyclicBarrier = new CyclicBarrier(2);


        Thread t1 = new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(4);
                cyclicBarrier.await();
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }

        });


        new Thread(() -> {
            try {
                cyclicBarrier.await();
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
        }).start();

        t1.start();


        TimeUnit.SECONDS.sleep(1);
        //BrokenBarrierException 被打断异常,  一个正在等待,另一个已经结束,此时reset 会抛出打断异常
        cyclicBarrier.reset();

在这里插入图片描述

最后

CyclicBarrier

  • 可以循环使用
  • 工作线程之间必须等到同一个点才能执行

CountDownLacth

  • CountDownLacth 不能reset
  • 工作线程之间彼此不关心