CountDownLatch,一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。

用给定的计数 初始化 CountDownLatch。由于调用了 countDown() 方法,所以在当前计数到达零之前,await 方法会一直受阻塞。
之后,会释放所有等待的线程,await 的所有后续调用都将立即返回。
这种现象只出现一次——计数无法被重置。如果需要重置计数,请考虑使用 CyclicBarrier。

CountDownLatch 是一个通用同步工具,它有很多用途。
将计数 1 初始化的 CountDownLatch 用作一个简单的开/关锁存器,或入口:在通过调用 countDown() 的线程打开入口前,所有调用 await的线程都一直在入口处等待。
用 N 初始化的 CountDownLatch 可以使一个线程在 N 个线程完成某项操作之前一直等待,或者使其在某项操作完成 N 次之前一直等待。

CountDownLatch 的一个有用特性是,它不要求调用 countDown 方法的线程等到计数到达零时才继续,而在所有线程都能通过之前,它只是阻止任何线程继续通过一个 await。

用法1: 下面给出了两个类,其中一组 worker 线程使用了两个倒计数锁存器: 
// 第一个类是一个启动信号,在 driver 为继续执行 worker 做好准备之前,它会阻止所有的 worker 继续执行。
// 第二个类是一个完成信号,它允许 driver 在完成所有 worker 之前一直等待。

class Driver {
void start() throws InterruptedException {
CountDownLatch startSignal = new CountDownLatch(1);
int N = 5;
CountDownLatch doneSignal = new CountDownLatch(N); for (int i = 0; i < N; i++) {
Worker worker = new Worker(startSignal, doneSignal,i);
Thread thread = new Thread(worker);
thread.start();
} doSomethingElse(1); // 所有线程都还没有开始执行
startSignal.countDown(); // 让所有线程开始执行
doSomethingElse(2);
doneSignal.await(); // 等待所有线程结束
doSomethingElse(3);
} // 执行一些其它的事情,具体结合实际情况
private void doSomethingElse(int i) {
System.out.println("doSomethingElse-"+i);
}
} class Worker implements Runnable {
private final CountDownLatch startSignal;
private final CountDownLatch doneSignal;
private final int i;
Worker(CountDownLatch startSignal, CountDownLatch doneSignal,int i) {
this.startSignal = startSignal;
this.doneSignal = doneSignal;
this.i=i;
} public void run() {
try {
startSignal.await();
doWork(i);
doneSignal.countDown();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
} void doWork(int i) {
System.out.println("doWork-"+i);
}
}

// 另一种典型用法2,将一个问题分成 N 个部分,用执行每个部分并让锁存器倒计数的 Runnable 来描述每个部分,然后将所有 Runnable
// 加入到 Executor 队列。当所有的子部分完成后,协调线程就能够通过
// await。(当线程必须用这种方法反复倒计数时,可改为使用CyclicBarrier。)

class Driver2 {
void start() throws InterruptedException {
int N = 5;
CountDownLatch doneSignal = new CountDownLatch(N);
ExecutorService e = Executors.newFixedThreadPool(3);
// 创建并执行线程
for (int i = 0; i < N; ++i) {
WorkerRunnable workerRunnable = new WorkerRunnable(doneSignal, i);
e.execute(workerRunnable);
}
// 等待所有线程结束
doneSignal.await();
//手动关闭,才会停止所有线程
e.shutdown();
}
} class WorkerRunnable implements Runnable {
private final CountDownLatch doneSignal;
private final int i; WorkerRunnable(CountDownLatch doneSignal, int i) {
this.doneSignal = doneSignal;
this.i = i;
} public void run() {
doWork(i);
doneSignal.countDown();
} void doWork(int i) {
System.out.println("doWork-" + i);
}
}

运行程序

package cn.fansunion.executorframework;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class CountDownLatchDemo { public static void main(String[] args) throws InterruptedException {
//Driver中的若干Thread,执行完毕后,自动就关闭了
Driver driver = new Driver();
driver.start();
//Driver2中,需要手动调用ExecutorService.shutdown关闭线程
Driver2 driver2 = new Driver2();
driver2.start();
} }

控制台结果
doSomethingElse-1
doSomethingElse-2
doWork-0
doWork-2
doWork-4
doWork-3
doWork-1
doSomethingElse-3
doWork-1
doWork-0
doWork-3
doWork-4
doWork-2

更多代码示例:
http://git.oschina.net/fansunion/Concurrent(逐步更新中)

参考资料:

有条件地终止 ScheduledExecutorService 中运行的定时任务
http://www.oschina.net/question/1158769_119659?sort=time

JDK API 文档

Java并发和多线程4:使用通用同步工具CountDownLatch实现线程等待的更多相关文章

  1. Java并发和多线程3:线程调度和有条件取消调度

    在第1篇中"并发框架基本示例",提到了Executors和ThreadPool.其中,还有个"定时调度"的方法,Executors.newScheduledTh ...

  2. java 利用同步工具类控制线程

    前言 参考来源:<java并发编程实战> 同步工具类:根据工具类的自身状态来协调线程的控制流.通过同步工具类,来协调线程之间的行为. 可见性:在多线程环境下,当某个属性被其他线程修改后,其 ...

  3. 【Java并发编程实战】-----“J.U.C”:CountDownlatch

    上篇博文([Java并发编程实战]-----"J.U.C":CyclicBarrier)LZ介绍了CyclicBarrier.CyclicBarrier所描述的是"允许一 ...

  4. java并发值多线程同步业务场景以及解决方案

    1.20个人排队同时访问2个购票窗口,同时能购票的只有两个人,当其中一个人买票完成后,18个人中的其中一个在占用窗口进行购买. 20个人相当于20个线程,2相当于资源,当18个人等待的时候,相当于线程 ...

  5. Java并发和多线程(一)基础知识

    1.java线程状态 Java中的线程可以处于下列状态之一: NEW: 至今尚未启动的线程处于这种状态. RUNNABLE: 正在 Java 虚拟机中执行的线程处于这种状态. BLOCKED: 受阻塞 ...

  6. Java并发编程(多线程)中的相关概念

    众所周知,在Java的知识体系中,并发编程是非常重要的一环,也是面试中必问的题,一个好的Java程序员是必须对并发编程这块有所了解的. 并发必须知道的概念 在深入学习并发编程之前,我们需要了解几个基本 ...

  7. Java并发和多线程:序

      近期,和不少公司的"大牛"聊了聊,当中非常多是关于"并发和多线程"."系统架构"."分布式"等方面内容的.不少问题, ...

  8. Java并发基础--多线程基础

    一.多线程基础知识 1.进程和线程 进程:是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程:进程也是程序的一次执行过程,是系统运行程序的基本单位:系统运行 ...

  9. Java并发和多线程2:3种方式实现数组求和

    本篇演示3个数组求和的例子. 例子1:单线程例子2:多线程,同步求和(如果没有计算完成,会阻塞)例子3:多线程,异步求和(先累加已经完成的计算结果) 例子1-代码 package cn.fansuni ...

随机推荐

  1. TensorFlow CNN 测试CIFAR-10数据集

    本系列文章由 @yhl_leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/50738311 1 CIFAR-10 数 ...

  2. Apach配置本地域名

    分三步: 一,开启虚拟域名设置,在路径中找到(apache\apache2.4.9\conf)httpd.conf 配置文件, 去掉 " Include conf/extra/httpd-v ...

  3. Python Study (05)装饰器

    装饰器(decorator)是一种高级Python语法.装饰器可以对一个函数.方法或者类进行加工.在Python中,我们有多种方法对函数和类进行加工,比如在Python闭包中,我们见到函数对象作为某一 ...

  4. JAVA学习第五十一课 — IO流(五)流的操作基本规律

    转换流: InputStreamReader:字节到字符的桥梁.解码 OutputStreamWriter:字符到字节的桥梁.编码 流的基本规律 1.明白源和汇 源:InputStream.Reade ...

  5. Linux安装vmtools

    unbantu下,先把DVD的Vmwarew.gz,文件拷贝到tmp文件.然后 tar zxf VMware Tools-0....... ls cd ./intall.pl 有个文件,先拷贝到roo ...

  6. Android 进程常驻(5)----开机广播的简单守护以及总结

    这是一个轻量级的库,配置几行代码.就能够实如今android上实现进程常驻,也就是在系统强杀下,以及360获取root权限下.clean master获取root权限下都无法杀死进程 支持系统2.3到 ...

  7. Java測试覆盖率工具----Cobertura,EclEmma

    Cobertura 是一个与Junit集成的代码覆盖率測量工具 它是免费.开源的 它能够与Ant和Maven集成.也能够通过命令行调用 能够生成HTML或XML格式的报告 能够依照不同的标准对HTML ...

  8. 英语发音规则---G字母

    英语发音规则---G字母 一.总结 一句话总结: 1.G发[g]音? bag [bæg] n. 袋:猎获物 go [gəʊ] vi. 走:达到 garden ['gɑːd(ə)n] n. 花园 gla ...

  9. luogu 1593 因子和

    因子和 题目描述 输入两个正整数a和b,求\(a^b\)的因子和.结果太大,只要输出它对9901的余数. 解法 基本算数定理,每一个数都可以被分解成一系列的素数的乘积,然后你可以分解出因数了. 如何求 ...

  10. 限制textfield的文字长度

    -(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementSt ...