线程同步工具CountDownLatch
CountDownLatch的一个非常典型的应用场景是:有一个任务想要往下执行,但必须要等到其他的任务执行完毕后才可以继续往下执行。假如我们这个想要继续往下执行的任务调用一个CountDownLatch对象的await()方法,其他的任务执行完自己的任务后调用同一个CountDownLatch对象上的countDown()方法,这个调用await()方法的任务将一直阻塞等待,直到这个CountDownLatch对象的计数值减到0为止。
CountDownLatch类有3个基本元素:
- 初始值决定CountDownLatch类需要等待的事件的数量。
- await() 方法, 被等待全部事件终结的线程调用。
- countDown() 方法,事件在结束执行后调用。
当创建 CountDownLatch 对象时,对象使用构造函数的参数来初始化内部计数器。每次调用 countDown() 方法, CountDownLatch 对象内部计数器减一。当内部计数器达到0时, CountDownLatch 对象唤醒全部使用 await() 方法睡眠的线程们。
不可能重新初始化或者修改CountDownLatch对象的内部计数器的值。一旦计数器的值初始后,唯一可以修改它的方法就是之前用的 countDown() 方法。当计数器到达0时, 全部调用 await() 方法会立刻返回,接下来任何countDown() 方法的调用都将不会造成任何影响。
此方法与其他同步方法有这些不同:
CountDownLatch 机制不是用来保护共享资源或者临界区。它是用来同步一个或者多个执行多个任务的线程。它只能使用一次。像之前解说的,一旦CountDownLatch的计数器到达0,任何对它的方法的调用都是无效的。如果你想再次同步,你必须创建新的对象。
CountDownLatch 类有另一种版本的 await() 方法,它是:
await(long time, TimeUnit unit): 此方法会休眠直到被中断; CountDownLatch 内部计数器到达0或者特定的时间过去了就会唤醒线程。TimeUnit 类包含了:DAYS, HOURS, MICROSECONDS, MILLISECONDS, MINUTES, NANOSECONDS, 和 SECONDS。
通过一个百米赛跑的例子加以说明:
package cn.darrenchan.bigdata.zklock; 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 { // 开始的倒数锁
final CountDownLatch begin = new CountDownLatch(1); // 结束的倒数锁
final CountDownLatch end = new CountDownLatch(10); // 十名选手
final 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();
Thread.sleep((long) (Math.random() * 10000));
System.out.println("No." + NO + " arrived");
} catch (InterruptedException 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();
}
}
运行效果:
Game Start
No.10 arrived
No.5 arrived
No.9 arrived
No.6 arrived
No.7 arrived
No.3 arrived
No.8 arrived
No.4 arrived
No.1 arrived
No.2 arrived
Game Over
参考:最简单的理解博客
线程同步工具CountDownLatch的更多相关文章
- Java核心知识点学习----线程同步工具类,CyclicBarrier学习
		线程同步工具类,CyclicBarrier日常开发较少涉及,这里只举一个例子,以做备注.N个人一块出去玩,相约去两个地方,CyclicBarrier的主要作用是等待所有人都汇合了,才往下一站出发. 1 ... 
- Java 线程同步组件 CountDownLatch 与 CyclicBarrier 原理分析
		1.简介 在分析完AbstractQueuedSynchronizer(以下简称 AQS)和ReentrantLock的原理后,本文将分析 java.util.concurrent 包下的两个线程同步 ... 
- 线程同步工具 Semaphore类使用案例
		参考博文 : 线程同步工具(一) 线程同步工具(二)控制并发访问多个资源 并发工具类(三)控制并发线程数的Semaphore 使用Semaphore模拟互斥锁 当一个线程想要访问某个共享资源,首先,它 ... 
- 线程同步工具 Semaphore类的基础使用
		推荐好文: 线程同步工具(一) 线程同步工具(二)控制并发访问多个资源 并发工具类(三)控制并发线程数的Semaphore 简介 Semaphore是基于计数的信号量,可以用来控制同时访问特定资源的线 ... 
- Java并发和多线程4:使用通用同步工具CountDownLatch实现线程等待
		CountDownLatch,一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待. 用给定的计数 初始化 CountDownLatch.由于调用了 countDown ... 
- 线程同步工具之CountDownLatch
		CountDownLatch,一个同步辅助类,在完成一组其他线程汇总执行的操作前,它允许一个或多个线程一直等待 主要方法: public CountDownLatch(int count); ... 
- JAVA线程同步辅助类CountDownLatch
		一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待. 用给定的计数 初始化 CountDownLatch.由于调用了 countDown() 方法,所以在当前计数到达 ... 
- Java多线程_同步工具CountDownLatch
		概念:CountDownLatch是多线程里面一个类似于计数器的高级同步工具,它的初始值代表线程的数量,当一个线程完成了任务后,CountDownLatch的值就减1,当值为0的时候,代表所有线程完成 ... 
- Java并发学习之十九——线程同步工具之Phaser
		本文是学习网络上的文章时的总结.感谢大家无私的分享. JDK 1.7 加入了一个新的工具Phaser.Phaser的在功能上与CountDownLatch有部分重合. 以下使用Phaser类来同步3个 ... 
随机推荐
- Android面试题(2)
			1.activity的生命周期 方法 描述 可被杀死 下一个 onCreate() 在activity第一次被创建的时候调用.这里是你做所有初始化设置的地方──创建视图.设置布局.绑定数据至列表等.如 ... 
- 假设这篇文章也能訪问过万,我的那些朋友就是SB
			能和我这个疯子交朋友的一定是神经病 
- EffectiveJava(28)怎么利用有限制的通配符类型来提升API的灵活性
			有时候,我们需要的灵活性要比不可变类型所能提供的更多.所以针对一些通用性的方法,通常用泛型代替固定的数据类型,特别是当你要将某个方法打包成Jar的时候. 结合之前的例子,我们增加尝试用有限制的通配符类 ... 
- iOS UITapGestureRecognizer手势和UIButton 以及UITabelView点击事件冲突
			一:在同一个view上加载,UITapGestureRecognizer手势,UIButton 行为,UITabelView点击事件冲突: 二:解决方式: 在UITapGesttureRecogniz ... 
- js数组高阶方法reduce经典用法代码分享
			以下是个人在工作中收藏总结的一些关于javascript数组方法reduce的相关代码片段,后续遇到其他使用这个函数的场景,将会陆续添加,这里作为备忘. javascript数组那么多方法,为什么我要 ... 
- taro + taro-ui + dva
			taro的安装及使用 安装 Taro 开发工具 @tarojs/cli 使用 npm 或者 yarn 全局安装,或者直接使用npx $ npm install -g @tarojs/cli $ yar ... 
- docker高级应用之cpu与内存资源限制(转)
			时间:2015-06-09 14:01:52 阅读:1581 评论:0 收藏:0 [点我收藏+] 标签:docker资源限制 docker cpu限制 ... 
- O2O研究系列——O2O知识思维导图整理
			本篇文章对O2O电子商务模式的常规知识点,使用思维导图的方式整理,表达的形式是名词纲领性的方式, 不会在图中详细说明各个点. 通过这个图研究O2O模式时,可以系统的对各个业务点进行更深入的研究,避免有 ... 
- java 判断一个字符串是否包含某个字符串中的字符
			public static void main(String[] args) { if(isHave("购买ab","出售AssBC")) Sy ... 
- iOS应用程序开发之应用间的跳转
			简介 配置和实现 判断应用启动方式 一.简介 最实际项目开发中,我们难免会遇到需要从一个应用跳转到另一个应用的情况.比如微信分享,实际就是一种应用间的跳转.但是有时候我们需要实现自己的两个应用间的跳转 ... 
