Java 并发编程系列: CountDownLatch (上厕所的案例)
1、What is CountDownLatch?
CountDownLatch提供了一种同步机制,可以允许一个或多个线程等待,直到其他线程上的一系列操作完成后,那个等待的线程再携手和其他线程继续走下去。用一句话大白话就是:我等你们,你们上完厕所,我再和你们一块出发。像这样的需求在java 中怎么实现呢?就需要使用CountDownLatch
。
要想学会使用CountDownLatch,只要搞清楚下面三个点,就可以了:
1、指定一个count。比如:CountDownLatch startSignal = new CountDownLatch(1);// 开始执行信号
2、明白await()
方法。当count变为0的时候就继续往下执行,没到0就一直卡着。
3、明白countDown()
方法。这个方法负责递减,每次减1。
概念简单的说一说,talk is cheap,还是上代码。
2、When should we use CountDownLatch ?
Use CountDownLatch when one of Thread like main thread, require to wait for one or more thread to complete, before its start doing processing.
当我们希望在main线程里,必须等待其他子线程执行完以后继续往下执行。这个时候,我们就需要用到CountDownLatch
。
按照上面的需求,在你不知道CountDownLatch之前,你也许会这样写你的代码:
我们希望输出这样的结果:
然而真正的输出结果是这样的:
使用了CountDownLatch后,像下面这样:
输出结果是一个顺序的,与主线程同步的状态:
3、How CountDownLatch works ?
现在我们来一步步复盘CountDownLatch执行顺序。
1、首先我们定义了CountDownLatch doneSignal = new CountDownLatch(N);
。完成信号。
2、然后我们定义了CountDownLatch startSignal = new CountDownLatch(1);
。开始信号。
3、然后我们使用for
循环来启动10个线程。我们分别把完成信号和开始信号传入线程。像这样:
for (int i = 1; i <= N; i++) { new Thread(new Worker(i,doneSignal, startSignal)).start();// 线程启动了
}
4、线程按理说已经开始执行了。然而,我们发现在Work
类中的run
方法里有这样一句话:
startSignal.await(); // 等待开始执行信号的发布
这句话导致了我们之前启动的10个线程全都处于等待状态,他们正在等待发号施令。那么这些阻塞的线程,什么时候开始运行呢? 根据前面我们说的,当count=0的时候就开始继续往下执行了。所以你也许知道下一步怎么触发他们了。 万事俱备,只欠东风!
5、给东风呗,让10个线程run起来了,没错,通过一句话就可以了:
startSignal.countDown();// 开始执行啦
我们通过countDown()
方法把count变为了0,这时候10个线程就跑起来了。 自然每个线程执行完都必须要--1啊,就是要调用完成信号的countDown()
方法。
6、就这样,当10个线程运行完以后,由于每个线程执行完都会对count减1。自然10个线程执行完以后,doneSignal
的count就为0。 我们知道,当count为0时,之前一直await的main线程,也就是主线程就继续往下执行了。
main线程的代码:
- 12 条用于 Linux 的 MySQL/MariaDB 安全最佳实践
- hdu----(4545)魔法串(LCS)
- Oracle压缩黑科技(二)—压缩数据的修改
- 在Pivotal Web Service上发布Spring Boot应用
- hdu---(1325)Is It A Tree?(并查集)
- spark2 sql编程样例:sql操作
- hdu----(1599)最大子矩阵(几何/dp)
- Go语言简单的TCP编程
- hdu---(1054)Strategic Game(最小覆盖边)
- Swagger Starter 1.4.0发布:新增swagger功能开源与全局参数的配置。
- Go语言语法汇总
- 整理的一些模版LCS(连续和非连续)
- 以太坊开发实战(第1部分:智能合约)
- spark2 sql读取数据源编程学习样例2:函数实现详解
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释