java 多线程 countdown_java多线程CountDownLatch

用视频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线程一直处于阻塞状态。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值