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. 【Codeforces 469B】Chat Online

    [链接] 我是链接,点我呀:) [题意] [题解] 因为你的朋友的时间是固定的. 你完全可以开一个tag[50]的数组,如果tag[i]=1说明i时刻你的基友在线(扫描基友的时间就能 得到 然后你在判 ...

  2. sso 登录业务逻辑

  3. hdu 2435 dinic算法模板+最小割性质

    #include<stdio.h> #include<queue> #include<string.h> using namespace std; #define ...

  4. ASP.NET学习笔记01

    ASP.NET初级工程师的核心要求:能够实现一个基本的网站. ASP.NET初级工程师面试主要要求: 1.基础的数据结构和算法 2.C#编程语言基础 3.网站基础(HTML,CSS,Javascrip ...

  5. 51nod 1413:权势二进制

    1413 权势二进制 题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题  收藏  关注 一个十进制整数被叫做权势二进制,当他的十进制 ...

  6. jQuery验证所有输入合法后才干提交

    大学三年里所有在专注后台编码.学会不知多少种,servlet.ssh,springMVC,web.py...... 最后每次碰到前端自己要写点东西就满目愁抑, 干脆自己好好理解一段前端代码, 特地拿出 ...

  7. js中的三种函数写法

    js中的三种函数写法 <script type="text/javascript"> //普通的声明方式 function myFun(m,n){ alert(m+n) ...

  8. word2010无法显示endnote x7插件及破解endnote x7

    最近本人由于要写文章需要使用endnotex7,相比于mendeley和noteexpress,文献管理和引用我喜欢endnote x7,阅读喜欢mendeley.可是由于之前用的正版30天到期了,破 ...

  9. shp系列(一)——利用C++进行shp文件的读(打开)与写(创建)开言

    博客背景和目的 最近在用C++写一个底层的东西,需要读取和创建shp文件.虽然接触shp文件已经几年了,但是对于shp文件内到底包含什么东西一直是一知半解.以前使用shp文件都是利用软件(如ArcGI ...

  10. vue.js的学习之路

    因为对jquery的ajax渲染很不满,所以我就来学vue.js了 1)vue.js是什么 官方解释为:Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架.与其它大型 ...