先上一个介绍: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线程一直处于阻塞状态。

最新文章

  1. Java_动态编译总结
  2. MVC模式与Android
  3. 【转】超实用PHP函数总结整理
  4. SPAN的高度问题
  5. Backtracking line search的理解
  6. Wifi开发技术总结1
  7. 菜鸟学习Spring——60s配置XML方法实现简单AOP
  8. SQL 不同的数据类型
  9. jquery get checkbox inside element(td).
  10. java中文乱码解决之道(四)—–java编码转换过程
  11. windows10,redhat6.5下python3.5.2使用cx_Oracle链接oracle
  12. android wheelview实现三级城市选择
  13. Oracle通用维、父子维相互转换
  14. 2.docker的网络模式
  15. Manjaro安装配置笔记
  16. perl常用总结
  17. C++ 解析json串
  18. php Allocator Jemalloc TCMalloc那个内存分配器比较好?
  19. mvc 部署到iis 提示错误未能加载文件或程序集System.Web.Http.WebHost
  20. tar.gz tar.bz2的解压命令

热门文章

  1. Android中通过Java代码实现ScrollView滚动视图-以歌词滚动为例
  2. Linux 文件、目录操作
  3. ELK学习005:Kibana 安装与运行
  4. python简明教程
  5. kong服务网关API
  6. springcloud服务已经关闭但是Eureka显示服务状态一直为UP
  7. Codeforces Round #340 (Div. 2) E XOR and Favorite Number 莫队板子
  8. Excel——排序筛选
  9. StackExchange.Redis 系列 1:基础使用
  10. python神器pycharm的安装