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类的使用的更多相关文章

  1. 基础知识(05) -- Java中的类

    Java中的类 1.类的概念 2.类中的封装 3.对象的三大特征 4.对象状态 5.类与类之间的关系 ------------------------------------------------- ...

  2. JAVA中的类和接口

    1.类: 类是具有相同属性和方法的一组对象的集合,它为属于该类的所有对象提供了统一的抽象描述,其内部包括属性和方法两个主要部分.在面向对象的编程语言中,类是一个独立的程序单位,它应该有一个类名并包括属 ...

  3. java中Color类的简单总结

    java中Color类的简单总结 1.颜色的常识 任何颜色都是由三原色组成(RGB),JAVA中支持224为彩色,即红绿蓝分量取值 介于0-255之间(8位表示) 2.Color类中的常量 publi ...

  4. Java中String类的方法及说明

    String : 字符串类型 一.      String sc_sub = new String(c,3,2);    //      String sb_copy = new String(sb) ...

  5. java中的类和对象

    Java中的类是一个模板,它用于描述一类对象的行为和状态. 对象则是类中的一个实例,对象有状态(属性)和行为(方法).例如一条狗就是一个对象,他的状态就是他的颜色,名字,品种:他的行为就是叫,摇尾巴, ...

  6. java中String类学习

    java中String类的相关操作如下: (1)初始化:例如,String s = “abc”; (2)length:返回字符串的长度. (3)charAT:字符操作,按照索引值获得字符串中的指定字符 ...

  7. 【JAVA零基础入门系列】Day11 Java中的类和对象

    今天要说的是Java中两个非常重要的概念--类和对象. 什么是类,什么又是对象呢?类是对特定集合的概括描述,比如,人,这个类,外观特征上,有名字,有年龄,能说话,能吃饭等等,这是我们作为人类的相同特征 ...

  8. 在java中String类为什么要设计成final

    在java中String类为什么要设计成final? - 胖胖的回答 - 知乎 https://www.zhihu.com/question/31345592/answer/114126087

  9. 关于Java中基类构造器的调用问题

    在<Java编程思想>第7章复用类中有这样一段话,值得深思.当子类继承了父类时,就涉及到了基类和导出类(子类)这两个类.从外部来看,导出类就像是一个与基类具有相同接口的新类,或许还会有一些 ...

随机推荐

  1. STM32F103RCT6移植到STM32F103C8T6注意事项

    1,修改IC为STC32F103C8 2,修改晶振为8.0M 3,修改C/C++宏定义,由STM32F10X_HD,USE_STDPERIPH_DRIVER 改为 STM32F10X_MD,USE_S ...

  2. 【HTML5开发系列】DOM及其相关

    对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标志语言的标准编程接口.DOM把Javascript和HTML文档的结构和内容连接起来,通过DOM可以控 ...

  3. zookeepeer ID生成器 (一)

    目录 写在前面 1.1. ZK 的分布式命名服务 1.1.1. 分布式 ID 生成器的类型 UUID方案 1.1.2. ZK生成分布式ID 写在最后 疯狂创客圈 亿级流量 高并发IM 实战 系列 疯狂 ...

  4. What Every Computer Scientist Should Know About Floating-Point Arithmetic

    http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

  5. font awesome (图标字体库)

    Font Awesome fa是什么? 图标字体库和CSS框架 怎么用? <link rel="stylesheet" href="https://cdn.boot ...

  6. Js中的Object.defineProperty

    通过Object.defineProperty为对象设置属性,并同时规定属性的属性(可见性,可配置性,可枚举性等) 备注:如果通过var obj = {} obj.age = 18这种方式设置的属性, ...

  7. centos 安装Phpstorm

    下载: http://www.jetbrains.com/phpstorm/download/#section=linux 解压: tar -zxf PhpStorm-8.0.1.tar.gz # 然 ...

  8. ubuntu 13.04 设定静态IP

    切换到root用户,然后进入/etc/network目录.备份interfaces文件(备份文件是一个好习惯) 下面编辑interfaces文件,添加如下语句: # Assgin static IP ...

  9. 七招从办公室政治中取胜 发表于 09 May 2008 ? 领导力培养

    办公室政治,对有些人来说是一个禁忌词汇,但在工作场合它却不可回避.简单说来,它就是职场上人与人的不同:观念的差异.利益的冲突 都可以看成是办公室政治的表现.它等于人与人之间的交流和关系.没必要害怕办公 ...

  10. 模仿jquery框架源码 -成熟---选择器

    <!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8& ...