CountDownLatch 和 CyclicBarrier的区别与详解

一.CountDownLatch 和 CyclicBarrier的区别

CountDownLatch 的计数器是大于或等于线程数的,而CyclicBarrier是一定等于线程数
CountDownLatch 放行由其他线程控制而CyclicBarrier是由本身来控制的

二.详解

CountDownLatch

说明: 一个线程等待其他线程执行完之后再执行,相当于加强版的join,在初始化CountDownLatch是需要设定计数器的数值(计数器数据不一定跟线程数相同,但是一定计数器的值一定是要大于等于线程数,一个线程中可以进行多次扣减。当计数器扣减至0时才可继续向下执行)

举例说明:
比如LOL在游戏开始时需要玩家全部准备完毕之后才开始,开始游戏可以理解为“主线程”,玩家准备理解为“其他线程”,在“其他线程”没有准备完毕之前,“主线程时等待状态”,当“其他线程”准备完毕之后“主线程”就会执行下一步开始游戏的动作
CountDownLatch 和 CyclicBarrier的区别与详解_第1张图片

代码示例

public class CountDownLatchTest {
    private static CountDownLatch countDownLatsh = new CountDownLatch(5);
    private static class Player implements Runnable{
        private Integer index;
        public Player(Integer index){
            this.index = index;
        }

        @Override
        public void run() {
            System.out.println("玩家"+index+"准备完成");
            countDownLatsh.countDown();
        }
    }

  
    public static void main(String[] args) throws InterruptedException {
    
        for(int i = 0; i < 5; i++){
            Player player = new Player(i);
            Thread thread = new Thread(player);
            thread.start();
        }
        countDownLatsh.await();

        System.out.println("玩家准备完毕,开始游戏");
    }
}
运行结果

玩家0准备完成
玩家1准备完成
玩家2准备完成
玩家3准备完成
玩家4准备完成
玩家准备完毕,开始游戏

cyclicbarrier
说明: 让一组线程到达某个屏障,然后被阻塞,一直到最后一个线程到达屏障,然后屏障开放,所有被阻塞的线程继续执行,计数器与线程数相等。
CyclicBarrier(int parties, Runnable barrierAction) 当时使用这个构造函数时,barrierAction定义的任务会执行

举例说明: 假设有一家公司要全体员工进行团建活动,活动内容为翻越三个障碍物,每一个人翻越障碍物所用的时间是不一样的。但是公司要求所有人在翻越当前障碍物之后再开始翻越下一个障碍物,也就是所有人翻越第一个障碍物之后,才开始翻越第二个,以此类推比如跨栏比赛,我们修改一下规则,当所有选手都跨过第一个栏杆是,才去跨第二个,以此类推,每一个员工都是一个“其他线程”。当所有人都翻越的所有的障碍物之后,程序才结束。而主线程可能早就结束了,这里我们不用管主线程。

CountDownLatch 和 CyclicBarrier的区别与详解_第2张图片

代码示例

public class CyclicBarrierTest {

    private static CyclicBarrier cyclicBarrier = new CyclicBarrier(5);
    
    public static class Surmount implements Runnable{
        @Override
        public void run() {

            try {
                for(int i = 1; i < 4; i++){
                    Random rand = new Random();
                    int randomNum = rand.nextInt((3000 - 1000) + 1) + 1000;//产生1000到3000之间的随机整数
                    Thread.sleep(randomNum);
                    String name = Thread.currentThread().getName();
                    System.out.println(name+"翻过了第" + i +"个障碍");
                    cyclicBarrier.await();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }
    
    public static void main(String[] args){
        for (int i = 1; i < 6; i++){
            Thread thread = new Thread(new Surmount(),"选手"+ i );
            thread.start();
        }
        System.out.println("main is end");
    }
}
运行结果:

main is end
选手4翻过了第1个障碍
选手2翻过了第1个障碍
选手1翻过了第1个障碍
选手5翻过了第1个障碍
选手3翻过了第1个障碍
选手1翻过了第2个障碍
选手4翻过了第2个障碍
选手3翻过了第2个障碍
选手5翻过了第2个障碍
选手2翻过了第2个障碍
选手5翻过了第3个障碍
选手2翻过了第3个障碍
选手1翻过了第3个障碍
选手4翻过了第3个障碍
选手3翻过了第3个障碍

原文链接:https://blog.csdn.net/wl_ang/article/details/104922464

你可能感兴趣的:(java,jvm,开发语言)