[笔记][Java7并发编程实战手冊]系列文件夹


简单介绍

本文学习CountDownLatch 倒计数闭锁。

本人英文不好。靠机器翻译,然后有一段非常形象的描写叙述,让我把它叫为倒计数

用给定的计数 初始化 CountDownLatch。由于调用了 countDown() 方法。所以在当前计数到达零之前。await 方法会一直受堵塞。

之后,会释放全部等待的线程,await 的全部兴许调用都将马上返回。这样的现象仅仅出现一次——计数无法被重置。 - jdk1.6里面的文档

能够看出,是由于会倒计数。并且计数器到0之后, 就不能再次使用该对象了(自断后路)。所以称为倒计数闭锁


CountDownLatch

是一个同步辅助类,在完毕一组正在其它线程中执行的操作之前,它同意一个或多个线程一直等待。

假如说:有a、b、c 三个线程。c 须要a,b线程的结果,所以C 须要等待 a,b 线程都执行完了,b 才干拿到正确的结果。 就是该类的一个使用场景

  1. countDown() 来计数(计时)
  2. await() 创建屏障点。等待计数到0的时候,await()方法后面的代码才执行。(换句话说。计数线程一起冲破这个屏障)
  3. getCount(): 是获取当前计数,不是总数
  4. 是辅助类! 不保证同步。

原理:

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倒计数闭锁的更多相关文章

  1. [笔记][Java7并发编程实战手冊]系列文件夹

    推荐学习多线程之前要看的书. [笔记][思维导图]读深入理解JAVA内存模型整理的思维导图文章里面的思维导图或则相应的书籍.去看一遍. 能理解为什么并发编程就会出现故障. Java7并发编程实战手冊 ...

  2. [笔记][Java7并发编程实战手冊]3.8 并发任务间的数据交换Exchanger

    [笔记][Java7并发编程实战手冊]系列文件夹 简单介绍 Exchanger 是一个同步辅助类.用于两个并发线程之间在一个同步点进行数据交换. 同意两个线程在某一个点进行数据交换. 本章exchan ...

  3. 那些年读过的书《Java并发编程实战》一、构建线程安全类和并发应用程序的基础

    1.线程安全的本质和线程安全的定义 (1)线程安全的本质 并发环境中,当多个线程同时操作对象状态时,如果没有统一的状态访问同步或者协同机制,不同的线程调度方式和不同的线程执行次序就会产生不同的不正确的 ...

  4. 【Java并发编程实战】—–synchronized

    在我们的实际应用其中可能常常会遇到这样一个场景:多个线程读或者.写相同的数据,訪问相同的文件等等.对于这样的情况假设我们不加以控制,是非常easy导致错误的. 在java中,为了解决问题,引入临界区概 ...

  5. Java并发编程实战 05等待-通知机制和活跃性问题

    Java并发编程系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 Java并发编程实战 03互斥锁 解决原子性问题 Java并发编程实 ...

  6. 《Java7并发编程实战手册》读书笔记

    一.线程管理 1.线程的创建和运行 创建线程的2种方式: 继承Thread类,并覆盖run()方法 创建一个实现Runnable接口的类.使用带参数的Thread构造器来创建Thread对象 每个Ja ...

  7. 《Go并发编程实战》读书笔记-语法概览

    <Go并发编程实战>读书笔记-语法概览 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 本篇博客我们会快速浏览一下Go的语法,内容涉及基本构成要素(比如标识符,关键字,子 ...

  8. 《Go并发编程实战》读书笔记-初识Go语言

    <Go并发编程实战>读书笔记-初识Go语言 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在讲解怎样用Go语言之前,我们先介绍Go语言的特性,基础概念和标准命令. 一. ...

  9. 《Java并发编程实战》读书笔记一 -- 简介

    <Java并发编程实战>读书笔记一 -- 简介 并发的历史 并发的历史,也是人类利用有限的资源去提高生产效率的一个的例子. 设想现在有台计算机,这台计算机具有以下的资源: 单核CPU一个 ...

随机推荐

  1. 利用“反射”动态加载R文件中的资源

    前几天做一个Android下面数据库相关的应用.用ListVIew展示表中数据的时候我希望能给表中每一条记录,加一个展示的图片.但是用数据库保存图片是比较难搞的.于是就把所需图片都保存到res下的dr ...

  2. Codeforces Round #198 (Div. 2)E题解

    E. Iahub and Permutations Iahub is so happy about inventing bubble sort graphs that he's staying all ...

  3. KAFKA 调优

    KAFKA 调优 最近要对kafka集群做调优,就在网上看了些资料,总结如下. 我们的kafka版本是0.10.1.0. 机器配置是40G内存,300G硬盘. 一共有3台机器组成一个小的集群. Kak ...

  4. 常用的CSS命名

    头:header 内容:content/container 尾:footer 导航:nav 侧栏:sidebar 栏目:column 页面外围控制整体佈局宽度:wrapper 左右中:left rig ...

  5. Android 自定义控件之圆形扩散View(DiffuseView)

    实现效果 使用 属性方法 代码 源码下载 参考链接 实现效果 使用 XML中: <com.airsaid.diffuseview.widget.DiffuseView android:id=&q ...

  6. 基于连接的Java网络编程

    实现了基于TCP的Java Socket编程,功能很简单:客户端向服务器端输出一名话"connect",服务器端接收输出到控制台并向客户端输出一名话"Hello" ...

  7. 实验6 Bezier曲线生成

    1.实验目的: 了解曲线的生成原理,掌握几种常见的曲线生成算法,利用VC+OpenGL实现Bezier曲线生成算法. 2.实验内容: (1) 结合示范代码了解曲线生成原理与算法实现,尤其是Bezier ...

  8. JavaScript是按引用传递or值传递?

    今遇js基础类型等问题,已经有点模糊,遂作总结. 前言: JavaScript原始类型:Undefined.Null.Boolean.Number.String.Symbol JavaScript引用 ...

  9. JS 垃圾回收机制

    [转自]:https://segmentfault.com/a/1190000018605776 垃圾回收 JavaScript 中的内存管理是自动执行的,而且是不可见的.我们创建基本类型.对象.函数 ...

  10. mysql 最大连接数

    方式一: 一次性修改  服务重启后还原 查看  show variables like 'max_connections%'; 修改 set GLOBAL max_connections=1024; ...