先上一个介绍: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的更多相关文章

  1. 转:java多线程CountDownLatch及线程池ThreadPoolExecutor/ExecutorService使用示例

    java多线程CountDownLatch及线程池ThreadPoolExecutor/ExecutorService使用示例 1.CountDownLatch:一个同步工具类,它允许一个或多个线程一 ...

  2. Java多线程-CountDownLatch、CyclicBarrier、Semaphore

    上次简单了解了多线程中锁的类型,今天要简单了解下多线程并发控制的一些工具类了. 1. 概念说明: CountDownLatch:相当于一个待执行线程计数器,当计数减为零时表示所有待执行线程都已执行完毕 ...

  3. java多线程 -- CountDownLatch 闭锁

    CountDownLatch 一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待. 用给定的计数 初始化 CountDownLatch.由于调用了 countDown ...

  4. java多线程-CountDownLatch

    简介 一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待.用给定的计数 初始化 CountDownLatch.由于调用了 countDown() 方法,所以在当前计数 ...

  5. java 多线程 CountDownLatch用法

    CountDownLatch,一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待. 主要方法 public CountDownLatch(int count); pu ...

  6. (转)java 多线程 CountDownLatch用法

    CountDownLatch,一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待. 主要方法 public CountDownLatch(int count); pu ...

  7. Java多线程20:多线程下的其他组件之CountDownLatch、Semaphore、Exchanger

    前言 在多线程环境下,JDK给开发者提供了许多的组件供用户使用(主要在java.util.concurrent下),使得用户不需要再去关心在具体场景下要如何写出同时兼顾线程安全性与高效率的代码.之前讲 ...

  8. Java多线程系列--“JUC锁”09之 CountDownLatch原理和示例

    概要 前面对"独占锁"和"共享锁"有了个大致的了解:本章,我们对CountDownLatch进行学习.和ReadWriteLock.ReadLock一样,Cou ...

  9. java多线程系列(八)---CountDownLatch和CyclicBarrie

    CountDownLatch 前言:如有不正确的地方,还望指正. 目录 认识cpu.核心与线程 java多线程系列(一)之java多线程技能 java多线程系列(二)之对象变量的并发访问 java多线 ...

随机推荐

  1. SQLServer之查询当前服务器下所有目录视图表

    SQL脚本 /*************1:删除临时表*************/ if exists(select * from tempdb..sysobjects where id=object ...

  2. 万科A顺利出局,布局一心堂

    万科的这两日的走势还不错,今日冲高回落,顺利出局. 那么有选中了一只 股票    一心堂 资金量W    12 建仓价格    22.2 加仓系数    1.5 加仓间隔    1.50% 总盈利比  ...

  3. 2020年如何成为一个高级AVA架构师(50W~100W年薪)

    2020年如何成为一个高级AVA架构师(50W~100W年薪)

  4. stlink 下载报错:Error Flash Download failed - "Cortext-M0+"

    stlink 下载报错:Error Flash Download failed - "Cortext-M0+" 解决方法: STM32 ST-LINK Utility 用这个软件把 ...

  5. Elasticsearch客户端源码剖析

    注:本文出自博主 Chloneda:个人博客 | 博客园 | Github | Gitee | 知乎 注:本文源链接:https://www.cnblogs.com/chloneda/p/es-cli ...

  6. 逻辑卷管理(LVM)-迁移

    逻辑卷管理(LVM)-迁移 更换卷组中逻辑卷中的一块硬盘流程:1确保卷组剩余空间大于需要更换的空间(缩减或添加添加新空间)-2迁移-3从卷组删除-4删除物理卷 #移除sdc1 1.查看卷组可用空间是否 ...

  7. python3-cookbook笔记:第六章 数据编码和处理

    python3-cookbook中每个小节以问题.解决方案和讨论三个部分探讨了Python3在某类问题中的最优解决方式,或者说是探讨Python3本身的数据结构.函数.类等特性在某类问题上如何更好地使 ...

  8. Oracle12c传统数据库模式 OGG

    OGG12C 配置 环境配置: 安装数据库Oracle12c 安装源端OGG:oggs  PORT:7809 安装目标端OGG:oggt   PORT:7909 源端和目标端地址:127.0.0.1 ...

  9. 纪中17日T1 2321. 方程

    纪中17日T1 2321. 方程 (File IO): input:cti.in output:cti.out 时间限制: 1000 ms  空间限制: 262144 KB  具体限制   Goto ...

  10. 剑指offer-面试题51-数组中的逆序对-归并排序

    /* 题目: 求给定数组的逆序对数. */ /* 思路: 归并排序. */ #include<iostream> #include<cstring> #include<v ...