[笔记][Java7并发编程实战手冊]3.4 等待多个并发事件的完毕CountDownLatch倒计数闭锁
简单介绍
本文学习CountDownLatch 倒计数闭锁。
本人英文不好。靠机器翻译,然后有一段非常形象的描写叙述,让我把它叫为倒计数
用给定的计数 初始化 CountDownLatch。由于调用了 countDown() 方法。所以在当前计数到达零之前。await 方法会一直受堵塞。
之后,会释放全部等待的线程,await 的全部兴许调用都将马上返回。这样的现象仅仅出现一次——计数无法被重置。 - jdk1.6里面的文档
能够看出,是由于会倒计数。并且计数器到0之后, 就不能再次使用该对象了(自断后路)。所以称为倒计数闭锁
CountDownLatch
是一个同步辅助类,在完毕一组正在其它线程中执行的操作之前,它同意一个或多个线程一直等待。
假如说:有a、b、c 三个线程。c 须要a,b线程的结果,所以C 须要等待 a,b 线程都执行完了,b 才干拿到正确的结果。 就是该类的一个使用场景
- countDown() 来计数(计时)
- await() 创建屏障点。等待计数到0的时候,await()方法后面的代码才执行。(换句话说。计数线程一起冲破这个屏障)
- getCount(): 是获取当前计数,不是总数
- 是辅助类! 不保证同步。
原理:
CountDownLatch是通过“共享锁”实现的。
在创建CountDownLatch中时,会传递一个int类型參数count,该參数是“锁计数器”的初始状态。表示该“共享锁”最多能被count给线程同一时候获取。当某线程调用该CountDownLatch对象的await()方法时,该线程会等待“共享锁”可用时,才干获取“共享锁”进而继续执行。而“共享锁”可用的条件,就是“锁计数器”的值为0!而“锁计数器”的初始值为count,每当一个线程调用该CountDownLatch对象的countDown()方法时,才将“锁计数器”-1。通过这样的方式。必须有count个线程调用countDown()之后,“锁计数器”才为0,而前面提到的等待线程才干继续执行。
演示样例
场景:密室大门将在七颗龙珠都被镶嵌到大门上的机关上时,密室大门才会打开。
以下的演示样例:讲述了一个密室(线程)。和7个工匠(线程)镶嵌龙珠, 最后密室大门被打开,守卫(主线程)复活的故事
/**
* Created by zhuqiang on 2015/8/19 0019.
*/
public class Client {
public static void main(String[] args) {
final CountDownLatch cd = new CountDownLatch(7); //创建辅助类7个倒计数
final Adytum adytum = new Adytum(cd);
new Thread(adytum).start();
for (int i = 0; i < 7; i++) {
new Thread(new Runnable() {
@Override
public void run() {
adytum.inlay();
}
}).start();
}
// 主线程 来模拟守卫吧。
try {
cd.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("守卫也复活了!");
}
}
//密室
class Adytum implements Runnable {
private CountDownLatch cd;
private long num = 7; // 记录剩余未被镶嵌的龙珠 ,用来对照和getCount返回的是否相等
private ReentrantLock lock = new ReentrantLock(); //创建同步锁。保证 inlay 中的资源计数 被正确计算。
public Adytum(CountDownLatch cd) {
this.cd = cd;
}
// 为密室大门服务的线程
@Override
public void run() {
System.out.println("欢迎来到密室。密室正等待被打开...");
try {
cd.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("当前龙珠已镶嵌%d颗。密室被打开了!欢呼吧\n",num);
}
/**
* 镶嵌龙珠到大门上
*/
public void inlay() {
try {
lock.lock(); // 把这里的锁去掉,能看到错误的计算数据,说明了CountDownLatch:不保证同步
long count = cd.getCount(); //返回当前还剩余计数
long time = (long) (Math.random() * 10); //模拟镶嵌了多少时间
System.out.printf("%s把龙珠镶嵌到了大门上,还有%d个龙珠未被镶嵌,计数是否和getCount相等:%s,此次镶嵌耗时:%d 秒\n", Thread.currentThread().getName(), count,count==num,time);
num--;
TimeUnit.SECONDS.sleep(time); //休眠辅助类。按指定单位休眠
cd.countDown(); //锁 保证是这个临界区内的代码同步。线程相互排斥,计算的结果正确被刷到主内存中。 不是说countDown方法须要来同步
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
未加锁的某一次执行结果:
把 lock.lock(); 加锁相关的代码凝视掉。
欢迎来到密室。密室正等待被打开...
Thread-1把龙珠镶嵌到了大门上,还有7个龙珠未被镶嵌,计数是否和getCount相等:true,此次镶嵌耗时:5 秒
Thread-2把龙珠镶嵌到了大门上,还有7个龙珠未被镶嵌,计数是否和getCount相等:true,此次镶嵌耗时:2 秒
Thread-4把龙珠镶嵌到了大门上,还有7个龙珠未被镶嵌,计数是否和getCount相等:true,此次镶嵌耗时:0 秒
Thread-3把龙珠镶嵌到了大门上,还有7个龙珠未被镶嵌,计数是否和getCount相等:true,此次镶嵌耗时:1 秒
Thread-6把龙珠镶嵌到了大门上,还有7个龙珠未被镶嵌,计数是否和getCount相等:true,此次镶嵌耗时:7 秒
Thread-5把龙珠镶嵌到了大门上,还有7个龙珠未被镶嵌,计数是否和getCount相等:true,此次镶嵌耗时:9 秒
Thread-7把龙珠镶嵌到了大门上,还有7个龙珠未被镶嵌,计数是否和getCount相等:true,此次镶嵌耗时:0 秒
守卫也复活了!
当前龙珠已镶嵌0颗,密室被打开了!欢呼吧
说明:能看到错误的计算数据,全是还有7个龙珠。说明了CountDownLatch:不保证同步,仅仅是达到 让一个线程或则多个线程等待
加锁的正确结果
欢迎来到密室,密室正等待被打开...
Thread-1把龙珠镶嵌到了大门上,还有7个龙珠未被镶嵌,计数是否和getCount相等:true,此次镶嵌耗时:2 秒
Thread-2把龙珠镶嵌到了大门上,还有6个龙珠未被镶嵌,计数是否和getCount相等:true,此次镶嵌耗时:0 秒
Thread-3把龙珠镶嵌到了大门上,还有5个龙珠未被镶嵌,计数是否和getCount相等:true,此次镶嵌耗时:5 秒
Thread-4把龙珠镶嵌到了大门上,还有4个龙珠未被镶嵌,计数是否和getCount相等:true,此次镶嵌耗时:5 秒
Thread-5把龙珠镶嵌到了大门上,还有3个龙珠未被镶嵌。计数是否和getCount相等:true,此次镶嵌耗时:0 秒
Thread-6把龙珠镶嵌到了大门上,还有2个龙珠未被镶嵌。计数是否和getCount相等:true,此次镶嵌耗时:2 秒
Thread-7把龙珠镶嵌到了大门上,还有1个龙珠未被镶嵌,计数是否和getCount相等:true,此次镶嵌耗时:5 秒
当前龙珠已镶嵌0颗,密室被打开了!欢呼吧
守卫也复活了!
说明:有密室,和守卫两个线程等待7个工匠线程把龙珠镶嵌完毕后,密室被打开,守卫也复活,得到了我们想要的正确结果
[笔记][Java7并发编程实战手冊]3.4 等待多个并发事件的完毕CountDownLatch倒计数闭锁的更多相关文章
- [笔记][Java7并发编程实战手冊]系列文件夹
推荐学习多线程之前要看的书. [笔记][思维导图]读深入理解JAVA内存模型整理的思维导图文章里面的思维导图或则相应的书籍.去看一遍. 能理解为什么并发编程就会出现故障. Java7并发编程实战手冊 ...
- [笔记][Java7并发编程实战手冊]3.8 并发任务间的数据交换Exchanger
[笔记][Java7并发编程实战手冊]系列文件夹 简单介绍 Exchanger 是一个同步辅助类.用于两个并发线程之间在一个同步点进行数据交换. 同意两个线程在某一个点进行数据交换. 本章exchan ...
- 那些年读过的书《Java并发编程实战》一、构建线程安全类和并发应用程序的基础
1.线程安全的本质和线程安全的定义 (1)线程安全的本质 并发环境中,当多个线程同时操作对象状态时,如果没有统一的状态访问同步或者协同机制,不同的线程调度方式和不同的线程执行次序就会产生不同的不正确的 ...
- 【Java并发编程实战】—–synchronized
在我们的实际应用其中可能常常会遇到这样一个场景:多个线程读或者.写相同的数据,訪问相同的文件等等.对于这样的情况假设我们不加以控制,是非常easy导致错误的. 在java中,为了解决问题,引入临界区概 ...
- Java并发编程实战 05等待-通知机制和活跃性问题
Java并发编程系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 Java并发编程实战 03互斥锁 解决原子性问题 Java并发编程实 ...
- 《Java7并发编程实战手册》读书笔记
一.线程管理 1.线程的创建和运行 创建线程的2种方式: 继承Thread类,并覆盖run()方法 创建一个实现Runnable接口的类.使用带参数的Thread构造器来创建Thread对象 每个Ja ...
- 《Go并发编程实战》读书笔记-语法概览
<Go并发编程实战>读书笔记-语法概览 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 本篇博客我们会快速浏览一下Go的语法,内容涉及基本构成要素(比如标识符,关键字,子 ...
- 《Go并发编程实战》读书笔记-初识Go语言
<Go并发编程实战>读书笔记-初识Go语言 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在讲解怎样用Go语言之前,我们先介绍Go语言的特性,基础概念和标准命令. 一. ...
- 《Java并发编程实战》读书笔记一 -- 简介
<Java并发编程实战>读书笔记一 -- 简介 并发的历史 并发的历史,也是人类利用有限的资源去提高生产效率的一个的例子. 设想现在有台计算机,这台计算机具有以下的资源: 单核CPU一个 ...
随机推荐
- devenv.exe 编译Solution
Build https://docs.microsoft.com/en-us/visualstudio/ide/reference/build-devenv-exe Builds a solution ...
- B1237 [SCOI2008]配对 贪心 + dp
我刚开始,我打眼一看:哇!网络流大水题,直接费用流板子,建边跟zz一样.结果看了一眼数据范围...gg,luogu上只能得30,直接建边就是n^2,1e5根本过不了.咋办,只能另谋出路.想不出来,看题 ...
- Vue2.0框架搭建基础操作及目录说明
一.概述 vue.js是一套构建用户界面的渐进式框架.vue采用自底向上增量开发的设计.vue的核心库只关心视图层,非常容易学习,非常容易与其它库和已有项目整合.vue完全有能力驱动采用单文件组件和v ...
- fastJson解析复杂对象时碰到的问题
碰到map对象无法解析出来,发现问题是缺少有get/set方法,否则无法解析. 对象转json字符串 JSON.toJSONString(module) json字符串转对象(必须是pojo) mod ...
- SQLServer 添加序号列
select ROW_NUMBER()OVER(ORDER BY 用来排序的列的列名),XXX,XXX from XXX 按照原始顺序: ROW_NUMBER()OVER(ORDER BY (sele ...
- BZOJ3573: [Hnoi2014]米特运输(树上乱搞)
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1669 Solved: 1031[Submit][Status][Discuss] Descript ...
- js中国各大城市快速选择代码
js中国各大城市快速选择插件 在线演示本地下载
- CorelDRAWX8新功能摆脱传统工作模式
最近,有一则好消息CorelDRAW X8特惠啦!功能不少价格却不高的CDR X8很快成了设计师们的新宠,三折之后你动心了么? 点击这里了解更多.. 那么CDR X8到底有何功能和亮点呢? 完全可自定 ...
- Ecshop 扯淡问题
1:解决 :在 temp 文件下创建 backup文件夹 修改权限 2:待补充...
- 修改XtraMessageBox的内容字体大小
修改XtraMessageBox的内容字体大小 public static DialogResult Show(UserLookAndFeel lookAndFeel, IWin32Window ow ...