CountDownLatch官方文档

一、原理

  CountDownLatch是一个非常实用的多线程控制工具类。Count Down在英文中意为倒计时,Latch意为门闩,可以简单的将CountDownLatch称为倒计时器。门闩的含义是:把门锁起来,不让里面的线程跑出来。因此,这个工具通常用来控制线程等待,它可以让一个线程等待知道倒计时结束,再开始执行。

  CountDownLatch内部维护着一个count计数,只不过对这个计数器的操作都是原子操作,同时只能有一个线程去操作这个计数器。CountDownLatch通过构造函数传入一个初始计数值,调用者可以通过调用CounDownLatch对象的countDown()方法,来使计数减1;如果调用对象上的await()方法,那么调用者就会一直阻塞在这里,直到别人通过countDown方法,将计数减到0,才可以继续执行。

  CountDownLatch的一种典型应用场景是火箭发射。在火箭发射前,为了保证万无一失,往往要进行各项设备、仪器的检查。只有等所有的检查完毕后,引擎才能点火。这种场景就非常适合使用CountDownLatch。它可以使得点火线程等待所有检查线程全部完成后再执行。

二、API

主要方法

  • public CountDownLatch(int count);

    构造方法参数指定了计数的次数

  • public void countDown();

    当前线程调用此方法,则计数减一

  • public void await() throws InterruptedException

    调用此方法会一直阻塞当前线程,直到计时器的值为0

三、用法

CountDownLatch的一种典型用法是:

a group of worker threads use two countdown latches(一组工作线程使用两个CountDownLatch)。

Sample usage: a group of worker threads use two countdown latches(一组工作线程使用两个CountDownLatch):

  • The first is a start signal that prevents any worker from proceeding until the driver is ready for them to proceed;
  • The second is a completion signal that allows the driver to wait until all workers have completed

下面以一个Demo来说明CountDownLatch的使用。

程序功能:模拟多线程下载,合并线程等到所有下载任务完成便开始合并。

/**
* CountDownLatch的典型用法2
* 代码功能:使用多个下载线程实现下载,等到所有任务完成后合并线程开始合并。
*
* @author lp
*
*/
public class CountDownLatchDemo2 { public static void main(String[] args) throws InterruptedException {
int N = 8;
CountDownLatch startSignal = new CountDownLatch(1);//startSignal控制开始
CountDownLatch doneSignal = new CountDownLatch(N);// ExecutorService executor = Executors.newFixedThreadPool(N + 1);// 8个下载线程,1个合并线程 // let all threads proceed
startSignal.countDown(); // N个下载任务开始执行
for (int i = 0; i < N; ++i) {
executor.execute(new DownloadRunnable(startSignal,doneSignal, i));
} // wait for all to finish
doneSignal.await();//阻塞,直到计数器为0 // 执行合并任务
executor.execute(new MergeRunnable()); executor.shutdown();
}
} /**
* 下载线程
*/
class DownloadRunnable implements Runnable {
private final CountDownLatch startSignal;
private final CountDownLatch doneSignal;
private final int i; public DownloadRunnable(CountDownLatch startSignal, CountDownLatch doneSignal, int i) {
this.startSignal = startSignal;
this.doneSignal = doneSignal;
this.i = i;
} public void run() {
try {
startSignal.await();//当前线程等待
doDownload(i);
doneSignal.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
} } private void doDownload(int i) {
System.out.println("Thead:" + i + "下载完成");
}
}

Another typical usage would be to divide a problem into N parts, describe each part with a Runnable that executes that portion and counts down on the latch, and queue all the Runnables to an Executor. When all sub-parts are complete, the coordinating thread will be able to pass through await. (When threads must repeatedly count down in this way, instead use a CyclicBarrier.)

另外一种典型的用法是:将一个问题分解成N部分,用Runnable来描述每一部分任务,每个Runnable执行完后将latch数减1,而且要将所有的Runnable都加入到Executor中。当所有子部分任务完成时,协调线程经过await后能够开始执行。(当线程必须可重复性的倒计时时,请使用CyclicBarrier代替)

/**
* CountDownLatch的典型用法1
* 代码功能:模拟多线程下载功能-使用多个下载线程实现下载,等到所有任务完成后合并线程开始合并。
*
* @author lp
*
*/
public class CountDownLatchDemo { public static void main(String[] args) throws InterruptedException {
int N = 8;
CountDownLatch doneSignal = new CountDownLatch(N);// 计数器从N开始倒数
ExecutorService executor = Executors.newFixedThreadPool(N + 1);// N个下载线程,1个合并线程 // N个下载任务开始执行
for (int i = 0; i < N; ++i) {
executor.execute(new DownloadRunnable(doneSignal, i));
} // wait for all to finish
doneSignal.await();//阻塞,直到计数器为0 // 执行合并任务
executor.execute(new MergeRunnable()); executor.shutdown();
}
} /**
* 下载线程
*/
class DownloadRunnable implements Runnable {
private final CountDownLatch doneSignal;
private final int i; DownloadRunnable(CountDownLatch doneSignal, int i) {
this.doneSignal = doneSignal;
this.i = i;
} public void run() {
doDownload(i);
doneSignal.countDown();
} private void doDownload(int i) {
System.out.println("Thead:" + i + "下载完成");
}
} /**
* 合并线程
*/
class MergeRunnable implements Runnable{ @Override
public void run() {
doMerge();
} private void doMerge(){
System.out.println("合并线程完成合并");
} }

线程工具类 - CountDownLatch(倒计时器)的更多相关文章

  1. Java并发工具类 - CountDownLatch

    Java并发工具类 - CountDownLatch 1.简介 CountDownLatch是Java1.5之后引入的Java并发工具类,放在java.util.concurrent包下面 http: ...

  2. Java中的4个并发工具类 CountDownLatch CyclicBarrier Semaphore Exchanger

    在 java.util.concurrent 包中提供了 4 个有用的并发工具类 CountDownLatch 允许一个或多个线程等待其他线程完成操作,课题点 Thread 类的 join() 方法 ...

  3. Java并发工具类CountDownLatch源码中的例子

    Java并发工具类CountDownLatch源码中的例子 实例一 原文描述 /** * <p><b>Sample usage:</b> Here is a pai ...

  4. 同步工具类 CountDownLatch 和 CyclicBarrier

    在开发中,一些异步操作会明显加快执行速度带来更好的体验,但同时也增加了开发的复杂度,想了用好多线程,就必须从这些方面去了解 线程的 wait() notify() notifyall() 方法 线程异 ...

  5. Java并发编程工具类 CountDownLatch CyclicBarrier Semaphore使用Demo

    Java并发编程工具类 CountDownLatch CyclicBarrier Semaphore使用Demo CountDownLatch countDownLatch这个类使一个线程等待其他线程 ...

  6. 25.大白话说java并发工具类-CountDownLatch,CyclicBarrier,Semaphore,Exchanger

    1. 倒计时器CountDownLatch 在多线程协作完成业务功能时,有时候需要等待其他多个线程完成任务之后,主线程才能继续往下执行业务功能,在这种的业务场景下,通常可以使用Thread类的join ...

  7. 并发是个什么鬼之同步工具类CountDownLatch

    扯淡 写这篇文章,我先酝酿一下,实不相瞒,脱离底层太久了,更确切的情况是,真没曾认真研究过.就目前来说,很多框架包括工具类已经把实现封装的很深,你只需轻轻的调用一下API,便不费半点力气.以至于大家会 ...

  8. java高并发系列 - 第16天:JUC中等待多线程完成的工具类CountDownLatch,必备技能

    这是java高并发系列第16篇文章. 本篇内容 介绍CountDownLatch及使用场景 提供几个示例介绍CountDownLatch的使用 手写一个并行处理任务的工具类 假如有这样一个需求,当我们 ...

  9. JAVA并发工具类---------------(CountDownLatch和CyclicBarrier)

    CountDownLatch是什么 CountDownLatch,英文翻译为倒计时锁存器,是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待. 闭锁可以延迟线程的进 ...

随机推荐

  1. 大型网站技术架构,4网站的高性能架构之Web前端性能优化

    一般说来Web前端指网站业务逻辑之前的部分,包括浏览器加载.网站视图模型.图片服务.CDN服务等,主要优化手段有优化浏览器访问.使用反向代理.CDN等. 4.2.1 浏览器访问优化 1.减少http请 ...

  2. QCOW2/RAW/qemu-img 概念浅析

    目录 目录 扩展阅读 RAW QCOW2 QEMU-COW 2 QCOW2 Header QCOW2 的 COW 特性 QCOW2 的快照 qemu-img 的基本使用 RAW 与 QCOW2 的区别 ...

  3. truncate()函数

    1 truncate()方法用于截断文件,如果指定了可选参数 size,则表示截断文件为 size 个字符,截断之后 size 后面的所有字符被删除. 参考: https://www.runoob.c ...

  4. EL表达式.jsp指令等

    1.JSP标准指令:<%@ 标准指令(属性 )%><%@ page %><%@ include %><%@ taglib %> 2.JSP程序代码元素: ...

  5. "SQLServer复制需要有实际的服务器名称才能连接到服务器,请指定实际的服务器名"

    最近在学习SQL SERVER的高级复制技术的时候,遇到一个小问题,就是用本地SQL SERVER连接服务器的数据库时,在查看复制功能的发布服务器时,连接不上,弹出一个错误提示框架,如下:原来在自己本 ...

  6. 2019寒假作业三:PTA7-1抓老鼠啊~亏了还是赚了

    - 抓老鼠啊~亏了还是赚了? ( 分) 某地老鼠成灾,现悬赏抓老鼠,每抓到一只奖励10元,于是开始跟老鼠斗智斗勇:每天在墙角可选择以下三个操作:放置一个带有一块奶酪的捕鼠夹(T),或者放置一块奶酪(C ...

  7. Socket服务端和客户端文件传输

    很多朋友在使用socket编程时不可避免的都做过文件传输,而视频电影等需要一个字节一个字节的传输:但是客户端一般都通过-1进行终止,服务也一样:但是存在的问题是客户端永远不会把-1传递给服务端:因此经 ...

  8. React手稿 - Context

    Context Context提供了除props之外的传参数的方式. Context是全局跨组件传递数据的. API React.createContext ``` const {Provider, ...

  9. Python中yield和return两者之间区别

    在任何函数都有返回值,一般都是想到return 关键词,在函数生成器中有个关键词 yield 也可以做返回值,在函数没调用之前,是不会输出任何东西的 1,return 用法 def stu(): re ...

  10. 让鼠标滚轮在WINDOWS系统中也和MAC一样滚动(WIN系统鼠标滚轮反向)

    用习惯MAC系统偶尔要用用WINDOWS系统,或者由于各种原因总之时不时需要由MAC转向WIN系统或同时需要两个平台机器上倒腾来倒腾去的同学,一般来说最痛苦的就是鼠标滚轮方向不一致. 基本上我们知道苹 ...