[笔记][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一个 ...
随机推荐
- [JavaEE] 了解Java连接池
转载自51CTO http://developer.51cto.com/art/201006/207768.htm 51CTO曾经为我们简单的介绍过Java连接池.要了解Java连接池我们先要了解数据 ...
- 第5章分布式系统模式 使用服务器激活对象通过 .NET Remoting 实现 Broker
正在使用 Microsoft? .NET Framework 构建一个需要使用分布式对象的应用程序.您的要求包括能够按值或按引用来传递对象,无论这些对象驻留在同一台计算机上,还是驻留在同一个局域网 ( ...
- 使用Micrisoft.net设计方案 第二章组织模式
第二章组织模式 模式不仅依赖于它所包含的更小模式,同时也依赖包含它的更大的模式.它是描述复杂软件的系统方法. 本章的目标是让我们了解以下问题: 1.如何标识模式与模式的关系 2.如何把模式组织成模式集 ...
- 11.javaweb国际化标签库
一.国际化标签库 1,格式化标签库提供的标签 2,标签详解 2.1<fmt:setLocale>标签 下面设置不同的区域,并在设置的区域下显示日期 2.2<fmt:requestEn ...
- 在无任何报错的情况下 pagehelper.startpage分页无效问题
问题原因:自从spring boot开始使用2.0x版本以上后,很多相应的依赖文件版本开始变化 该版本为spring-boot 1.4.1 <dependency> <groupId ...
- 【Oracle】搭建DG(DataGuard)
操作系统:OEL 5.6 Oracle 版本:11.2.0.4.0 DataGuard规划说明 DATABASE_ROLE DB_NAME IPADDR Primary lgr 192.168.10. ...
- Jmeter报内存溢出解决方案
描述:wimdows环境,做上传图片接口测试,涉及图片合成和上传,图片采用base64编码.每1s启动200线程的时候,Jmeter报内存溢出错误. 解决方案: 1.修改jmeter.bat: set ...
- js 或运算
表达式a && 表达式b : 计算表达式a(也可以是函数)的运算结果, 如果为 True, 执行表达式b(或函数),并返回b的结果: 如果为 False,返回a的结果: 表达式a || ...
- children ie8下获取错误
ParentNode.children 是一个只读属性,返回 一个Node的子elements,是一个动态更新的 HTMLCollection. Internet Explorer 6 - 8 支持该 ...
- WPF创建自定义控件并运用
此项目源码:https://github.com/lizhiqiang0204/WpfCustomControlLibrary1 首先创建自定义控件库项目 项目名称命名为:WpfCustomContr ...