Java中CountDownLatch类的使用
0、CountDownLatch作用
1) Java api中的解释:一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。
2) CountDownLatch可以使Java线程阻塞在某个地方,当达到某个条件时(CountDownLatch的等待计数为0),线程才继续往后执行。
1、实例 (参考http://blog.csdn.net/shihuacai/article/details/8856370)
1) 需求
10个运动员进行100米赛跑,要求裁判发出命令时,比赛开始,并打印出10名选手到达终点的顺序。
2) 代码
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class CountDownLatchTest {
// 模拟了100米赛跑,10名选手已经准备就绪,只等裁判一声令下。当所有人都到达终点时,比赛结束。
public static void main(String[] args) throws InterruptedException {
// 开始的倒数锁
CountDownLatch begin = new CountDownLatch(1);
// 结束的倒数锁
CountDownLatch end = new CountDownLatch(10);
// 十名选手
ExecutorService exec = Executors.newFixedThreadPool(10);
for (int index = 0; index < 10; index++) {
final int NO = index + 1;
Runnable run = new Runnable() {
public void run() {
try {
// 等待
begin.await();
System.out.println("选手" + NO + " 到达终点");
} catch (Exception e) {
} finally {
// 每个选手到达终点时,end就减一
end.countDown();
}
}
};
exec.submit(run);
}
System.out.println("Game Start");
// begin减一,开始游戏
begin.countDown();
// 等待end变为0,即所有选手到达终点
end.await();
System.out.println("Game Over");
exec.shutdown();
}
}
3) 解释
- 第10行,12行分别创建2个CountDownLatch,倒数锁分别为1和10,
- 第15~31行的for循环,定义10是Runnable任务,每个任务代表一名选手到达终点。
- 第30(exec.submit(run))行是将创建的10个Runnable任务提交至线程池。每次将任务提交线程池(exec.submit(run)),该任务都会阻塞在第21行处(begin.await(),因为此时begin的倒数锁是1,不是0),for循环执行完毕后,线程池exec中装了10个Ruunable任务,每个任务都阻塞在begin.await()处。
- 第34行(begin.countDown())执行完成后,begin的倒数锁变为0,此时线程池exec中阻塞的10个任务并发执行,而主线程则阻塞在第36行(end.await(),因为end的倒数锁不为0),每执行完一个,end的倒数锁减一,10个任务全部执行完成后,end倒数锁变为0,主线程继续执行,打印Game Over。
4) 结果

5) 相关分析
若注释掉第21行(begin.await()),则在for循环中,每创建一个Runnable后,会提交至线程池,该Runnable便会执行,所以预期结果会是顺序打印1至10号选手,但结果如下,并不是顺序打印1至10号选手

可以发现,虽然不是顺序打印1至10号选手,但总体打印顺序基本是从小到大(可执行多次验证),这是因为多线程的结果(10个任务虽然按选手1~10顺序提交,但因为并行执行任务,所以并不会完全顺序打印1至10号选手,但总体还是呈现任务早提交,早执行的现象)。
为此我们在程序中增加一行,第31行,并注释掉第21行,代码如下
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class CountDownLatchTest {
// 模拟了100米赛跑,10名选手已经准备就绪,只等裁判一声令下。当所有人都到达终点时,比赛结束。
public static void main(String[] args) throws InterruptedException {
// 开始的倒数锁
CountDownLatch begin = new CountDownLatch(1);
// 结束的倒数锁
CountDownLatch end = new CountDownLatch(10);
// 十名选手
ExecutorService exec = Executors.newFixedThreadPool(10);
for (int index = 0; index < 10; index++) {
final int NO = index + 1;
Runnable run = new Runnable() {
public void run() {
try {
// 等待
// begin.await();
System.out.println("选手" + NO + " 到达终点");
} catch (Exception e) {
} finally {
// 每个选手到达终点时,end就减一
end.countDown();
}
}
};
exec.submit(run);
Thread.sleep(1000);
}
System.out.println("Game Start");
// begin减一,开始游戏
begin.countDown();
// 等待end变为0,即所有选手到达终点
end.await();
System.out.println("Game Over");
exec.shutdown();
}
}
这样,每个Runnable任务提交至线程池后会等待1s,运行结果如下:

该结果10个Runnable任务顺序执行,因为每个任务提交至线程池后等待一秒,在这一秒内,该Runnable任务已经执行完成,所以10个任务会顺序执行。
当取消注释第21行时,运行结果如下:

此时,10个Runnable任务没有顺序执行,是因为每次讲任务提交至线程池后,虽然等待1秒,但该任务运行至第21行时,会阻塞住,所以for循环执行完后,线程池中会有10个Runnable任务,这10个任务全都阻塞在第21行(begin.await()),当主线程运行完第35行后,begin倒数锁变为0,被阻塞的10个Runnable任务并行执行,所以运行结果是无序的。
Java中CountDownLatch类的使用的更多相关文章
- 基础知识(05) -- Java中的类
Java中的类 1.类的概念 2.类中的封装 3.对象的三大特征 4.对象状态 5.类与类之间的关系 ------------------------------------------------- ...
- JAVA中的类和接口
1.类: 类是具有相同属性和方法的一组对象的集合,它为属于该类的所有对象提供了统一的抽象描述,其内部包括属性和方法两个主要部分.在面向对象的编程语言中,类是一个独立的程序单位,它应该有一个类名并包括属 ...
- java中Color类的简单总结
java中Color类的简单总结 1.颜色的常识 任何颜色都是由三原色组成(RGB),JAVA中支持224为彩色,即红绿蓝分量取值 介于0-255之间(8位表示) 2.Color类中的常量 publi ...
- Java中String类的方法及说明
String : 字符串类型 一. String sc_sub = new String(c,3,2); // String sb_copy = new String(sb) ...
- java中的类和对象
Java中的类是一个模板,它用于描述一类对象的行为和状态. 对象则是类中的一个实例,对象有状态(属性)和行为(方法).例如一条狗就是一个对象,他的状态就是他的颜色,名字,品种:他的行为就是叫,摇尾巴, ...
- java中String类学习
java中String类的相关操作如下: (1)初始化:例如,String s = “abc”; (2)length:返回字符串的长度. (3)charAT:字符操作,按照索引值获得字符串中的指定字符 ...
- 【JAVA零基础入门系列】Day11 Java中的类和对象
今天要说的是Java中两个非常重要的概念--类和对象. 什么是类,什么又是对象呢?类是对特定集合的概括描述,比如,人,这个类,外观特征上,有名字,有年龄,能说话,能吃饭等等,这是我们作为人类的相同特征 ...
- 在java中String类为什么要设计成final
在java中String类为什么要设计成final? - 胖胖的回答 - 知乎 https://www.zhihu.com/question/31345592/answer/114126087
- 关于Java中基类构造器的调用问题
在<Java编程思想>第7章复用类中有这样一段话,值得深思.当子类继承了父类时,就涉及到了基类和导出类(子类)这两个类.从外部来看,导出类就像是一个与基类具有相同接口的新类,或许还会有一些 ...
随机推荐
- Java 学习 day09
01-面向对象(内部类访问规则) package myFirstCode; /* 内部类的访问规则: 1. 内部类可以直接访问外部类的成员,包括私有private. 之所以可以直接访问外部类中的成员, ...
- iOS解决导航引起视图高度问题
经过导航栏跨越的坑,总结出有两种方法可以无痕解决(前提>=iOS7版本)(TabBar与导航栏类似) 1.通过设置导航栏的透明度实现(这种方式的控制器view的起始坐标是充(0,64)开始的) ...
- POJ3094 Sky Code(莫比乌斯反演)
POJ3094 Sky Code(莫比乌斯反演) Sky Code 题意 给你\(n\le 10^5\)个数,这些数\(\le 10^5\),问这些这些数组成的互不相同的无序四元组(a,b,c,d)使 ...
- 我的Android进阶之旅------>Android嵌入图像InsetDrawable的用法
面试题:为一个充满整个屏幕的LinearLayout布局指定背景图,是否可以让背景图不充满屏幕?请用代码描述实现过程. 解决此题,可以使用嵌入(Inset)图像资源来指定图像,然后像使用普通图像资源一 ...
- 批处理设置IP地址
echo offecho 修改[本地连接]IP......netsh interface IP set address "本地连接" static 138.8.8.111 255. ...
- Yii2发送短信验证码完全解决方案
概述 在做项目的时候,需要用到短信发送验证码功能.不能不说Yii2的牛逼,很容易就搞定了.下面我整理一下具体功能和流程,分享给大家. 主要功能 通过Yii2 rules验证手机号 通过js验证是否为手 ...
- Linux中查找文件和文件内容的常用命令
一.whereis <程序名称> 查找软件的安装路径-b 只查找二进制文件 -m 只查找帮助文件-s 只查找源代码-u 排除指定类型文件-f 只显示文件名-B <目录> 在指定 ...
- 搭建SSM项目时报错(org.springframework.jdbc.CannotGetJdbcConnectionException)
严重: Servlet.service() for servlet [SpringMVC] in context with path [/ssm] threw exception [Request p ...
- 【九】MongoDB管理之安全性
要保证一个安全的MongoDB运行环境,DBA需要实施一些控制保证用户或应用程序仅仅访问它们需要的数据.这些措施包括但不限于: 认证机制 基于角色的访问控制 加密 审计 一.认证机制 认证是验证客户端 ...
- PHP新写的大转盘抽奖源码
中奖概率 抽奖大转盘演示:http://www.sucaihuo.com/php/3301.html function getRand($proArr, $proCount) { $result = ...