java多线程CountDownLatch
先上一个介绍: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的更多相关文章
- 转:java多线程CountDownLatch及线程池ThreadPoolExecutor/ExecutorService使用示例
java多线程CountDownLatch及线程池ThreadPoolExecutor/ExecutorService使用示例 1.CountDownLatch:一个同步工具类,它允许一个或多个线程一 ...
- Java多线程-CountDownLatch、CyclicBarrier、Semaphore
上次简单了解了多线程中锁的类型,今天要简单了解下多线程并发控制的一些工具类了. 1. 概念说明: CountDownLatch:相当于一个待执行线程计数器,当计数减为零时表示所有待执行线程都已执行完毕 ...
- java多线程 -- CountDownLatch 闭锁
CountDownLatch 一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待. 用给定的计数 初始化 CountDownLatch.由于调用了 countDown ...
- java多线程-CountDownLatch
简介 一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待.用给定的计数 初始化 CountDownLatch.由于调用了 countDown() 方法,所以在当前计数 ...
- java 多线程 CountDownLatch用法
CountDownLatch,一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待. 主要方法 public CountDownLatch(int count); pu ...
- (转)java 多线程 CountDownLatch用法
CountDownLatch,一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待. 主要方法 public CountDownLatch(int count); pu ...
- Java多线程20:多线程下的其他组件之CountDownLatch、Semaphore、Exchanger
前言 在多线程环境下,JDK给开发者提供了许多的组件供用户使用(主要在java.util.concurrent下),使得用户不需要再去关心在具体场景下要如何写出同时兼顾线程安全性与高效率的代码.之前讲 ...
- Java多线程系列--“JUC锁”09之 CountDownLatch原理和示例
概要 前面对"独占锁"和"共享锁"有了个大致的了解:本章,我们对CountDownLatch进行学习.和ReadWriteLock.ReadLock一样,Cou ...
- java多线程系列(八)---CountDownLatch和CyclicBarrie
CountDownLatch 前言:如有不正确的地方,还望指正. 目录 认识cpu.核心与线程 java多线程系列(一)之java多线程技能 java多线程系列(二)之对象变量的并发访问 java多线 ...
随机推荐
- python+selenium自动化测试,浏览器最大化报错解决方法
此处以谷歌浏览器为例 [问题1]缺少chrome驱动,webdriver调用谷歌浏览器的时候就报错了,如下图: [原因分析]缺少谷歌驱动程序 [解决办法] 1.查看本地安装chrome浏览器版本 2. ...
- Linux 文件、目录操作
Linux中的路径只能使用/,不能使用\ 或\\. cd 切换目录 cd / 切换到系统根目录,cd即change dir cd /bin 切换到根目录下的bin目录 cd .. ...
- 邓 【PHP大全】
获取对应的时间戳(只保存月底的时间戳) function getTimeDate($timeType, $time, $count) { switch ($timeType) { case 'MONT ...
- 字节码操作、javassist使用
一.功能 1.动态生成新的类 2.动态改变某个类的结构(添加.删除.修改 新的属性.方法) 二.优势 1.比反射开销小,性能高 2.JAVAasist性能高于反射,低于ASM 使用javassis ...
- Bellman-ford算法 无向图
// 单源最短路问题 // Bellman-Ford算法 // 复杂度O(V*E) //! 可以判断负圈 #include <cstdio> #include <iostream&g ...
- VS自定义模板-以自定义类模板为样例
前言 在实际的工作过程中部分公司会要求开发人员在开发过程中需遵守一些开发规范,开发规范中主要包括文件的注释规范,项目.文件.变量的命名规范(例如驼峰规范)等等.例如我们代码规范中就有一项新增文件的文件 ...
- 正则表达式中的exec()方法
推荐该博主的内容链接: https://blog.csdn.net/ddwddw4/article/details/84658398?ops_request_misc=%7B%22request%5F ...
- Docker Stack 学习笔记
该文为<深入浅出Docker>的学习笔记,感谢查看,如有错误,欢迎指正 一.简介 Docker Stack 是为了解决大规模场景下的多服务部署和管理,提供了期望状态,滚动升级,简单易用,扩 ...
- Javaweb项目中修改表单时数据回显方法
1.前言 先来说下什么是数据回显,比如我要修改我的个人信息,点击修改按钮后进入修改界面,在这个界面中直接将原来的信息显示在表单中,而不是空表单,这就是数据回显 2.思路 当点击修改的时候,从数据库中查 ...
- What is NodeJS(学习过程)
为什么要学习node.首先是听说了这个和前后端分离有很大的关系.node作为一个基础的技术,需要提前学习.学习node,不打算直接先跟着视频去学习老师们的课程.因为想自己找到一种适合自己的学习方法.之 ...