码迷,mamicode.com
首页 > 编程语言 > 详细

java多线程CountDownLatch

时间:2020-02-25 20:29:38      阅读:72      评论:0      收藏:0      [点我收藏+]

标签:lib   getname   VID   函数返回   是什么   junit单元测试   java   article   视频   

先上一个介绍:https://blog.csdn.net/shihuacai/article/details/8856370


用视频https://www.bilibili.com/video/av81181427 中的一个例子来测试

    @Test
    public void countdownlatch ()throws InterruptedException {
        /*
            这个5不能循环,减到0了之后await作用就消失了
         */
        CountDownLatch countDownLatch=new CountDownLatch(5);
        for(int i=0;i<5;i++){
            new Thread(()->{
                try{
                    Thread.sleep(new Double(Math.random()*3000).longValue());
                    System.out.println(Thread.currentThread().getName()+"玩家准备就绪");
                    countDownLatch.countDown();//计数点
                    System.out.println(Thread.currentThread().getName()+"玩家选择英雄");
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
            }).start();
        }
        countDownLatch.await();
       System.out.println(Thread.currentThread().getName()+"开始游戏");
        //Thread.sleep(3000);
    }

输出为:

Thread-0玩家准备就绪
Thread-0玩家选择英雄
Thread-2玩家准备就绪
Thread-2玩家选择英雄
Thread-4玩家准备就绪
Thread-4玩家选择英雄
Thread-3玩家准备就绪
Thread-3玩家选择英雄
Thread-1玩家准备就绪
Thread-1玩家选择英雄
main开始游戏

实际上,CountDownLatch阻塞的是主线程而非子线程,这一点要弄清楚。子线程中countDownLatch.countDown();唯一的作用就是将CountDownLatch对象内部的计数器减一,它不能起到阻塞子线程的作用。唯一受到阻塞的是创建完子线程后执行countDownLatch.await();语句的父线程,只有CountDownLatch对象内的计数器减到0之后主线程才能继续执行,而这和子线程的执行无关。
说明这一点最直观的方式是让CountDownLatch的初始参数比线程数小,我们把参数调成5,用10个线程。看看输出是什么:

Thread-4玩家准备就绪
Thread-4玩家选择英雄
Thread-7玩家准备就绪
Thread-7玩家选择英雄
Thread-6玩家准备就绪
Thread-6玩家选择英雄
Thread-5玩家准备就绪
Thread-5玩家选择英雄
Thread-3玩家准备就绪
Thread-3玩家选择英雄
main开始游戏

为什么只有5个子线程执行的结果,剩下的5个子线程去哪里了?别急,我们在主线程的代码末尾加一句sleep语句:

        countDownLatch.await();
        System.out.println(Thread.currentThread().getName()+"开始游戏");
        Thread.sleep(3000);

再次执行,结果是:

Thread-7玩家准备就绪
Thread-7玩家选择英雄
Thread-9玩家准备就绪
Thread-9玩家选择英雄
Thread-2玩家准备就绪
Thread-2玩家选择英雄
Thread-6玩家准备就绪
Thread-6玩家选择英雄
Thread-0玩家准备就绪
Thread-0玩家选择英雄
main开始游戏
Thread-5玩家准备就绪
Thread-5玩家选择英雄
Thread-4玩家准备就绪
Thread-4玩家选择英雄
Thread-1玩家准备就绪
Thread-1玩家选择英雄
Thread-3玩家准备就绪
Thread-3玩家选择英雄
Thread-8玩家准备就绪
Thread-8玩家选择英雄

可以看出,之前剩下五个子线程的内容输出不出来,是因为父线程执行完后函数返回了。但是我们知道,父线程和子线程是独立执行的。这是为什么?
其实这是因为我使用的是Junit测试方法,而Junit不支持多线程而已,这个帖子就提到了这一点:在junit单元测试中,当创建了新线程后,单元测试并不会等待主线程下启动的新线程是否执行结束,只要主线程结束完成,单元测试就会关闭,导致主线程中启动的新线程不能顺利执行完.所以剩下的五个线程还没有执行就被销毁了。
换成普通的main方法再试试:

Thread-0玩家准备就绪
Thread-0玩家选择英雄
Thread-5玩家准备就绪
Thread-5玩家选择英雄
Thread-3玩家准备就绪
Thread-3玩家选择英雄
Thread-1玩家准备就绪
Thread-1玩家选择英雄
Thread-9玩家准备就绪
Thread-9玩家选择英雄
main开始游戏
Thread-7玩家准备就绪
Thread-7玩家选择英雄
Thread-8玩家准备就绪
Thread-8玩家选择英雄
Thread-2玩家准备就绪
Thread-2玩家选择英雄
Thread-6玩家准备就绪
Thread-6玩家选择英雄
Thread-4玩家准备就绪
Thread-4玩家选择英雄

Process finished with exit code 0

这回就正常了
那如果CountDownLatch的初始参数比线程数大会发生什么,我们把参数调成10,用5个线程。

Thread-2玩家准备就绪
Thread-2玩家选择英雄
Thread-1玩家准备就绪
Thread-1玩家选择英雄
Thread-0玩家准备就绪
Thread-0玩家选择英雄
Thread-4玩家准备就绪
Thread-4玩家选择英雄
Thread-3玩家准备就绪
Thread-3玩家选择英雄

实际上,虽然子线程都执行完了,程序还是不会停止的,因为CountDownLatch内的计数器不会被减到0,main线程一直处于阻塞状态。

java多线程CountDownLatch

标签:lib   getname   VID   函数返回   是什么   junit单元测试   java   article   视频   

原文地址:https://www.cnblogs.com/jiading/p/12363051.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!