「java.util.concurrent并发包」之 CountDownLatch
一 CountDownLatch是什么
二 CountDownLatch如何工作
CountDownLatch.java类中定义的构造函数:
public void CountDownLatch(int count) {...}
构造器中的计数值(count)实际上就是闭锁需要等待的线程数量。这个值只能被设置一次,而且CountDownLatch没有提供任何机制去重新设置这个计数值。
与CountDownLatch的第一次交互是主线程等待其他线程。主线程必须在启动其他线程后立即调用CountDownLatch.await()方法。这样主线程的操作就会在这个方法上阻塞,直到其他线程完成各自的任务。
其他N 个线程必须引用闭锁对象,因为他们需要通知CountDownLatch对象,他们已经完成了各自的任务。这种通知机制是通过 CountDownLatch.countDown()方法来完成的;每调用一次这个方法,在构造函数中初始化的count值就减1。所以当N个线程都调 用了这个方法,count的值等于0,然后主线程就能通过await()方法,恢复执行自己的任务。
三 在实时系统中的使用场景
- 实现最大的并行性:有时我们想同时启动多个线程,实现最大程度的并行性。例如,我们想测试一个单例类。如果我们创建一个初始计数为1的CountDownLatch,并让所有线程都在这个锁上等待,那么我们可以很轻松地完成测试。我们只需调用 一次countDown()方法就可以让所有的等待线程同时恢复执行。
- 开始执行前等待n个线程完成各自任务:例如应用程序启动类要确保在处理用户请求前,所有N个外部系统已经启动和运行了。
- 死锁检测:一个非常方便的使用场景是,你可以使用n个线程访问共享资源,在每次测试阶段的线程数目是不同的,并尝试产生死锁。
四 代码实例
描述: 在这个例子中,我们有一个应用调用主类,所有外部系统准备(数据,资源,网络准备等)结束后通知闭锁,主类一致在闭锁等待,直到所有外部准备完成。
抽象类定义: 抽象准备接口(抽象类)
public abstract class BasePreparer implements Runnable {
private CountDownLatch countDownLatch;
private String prepareName;
private boolean prepareDone;
public BasePreparer(String prepareName, CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
this.prepareName = prepareName;
this.prepareDone = false;
}
protected abstract void prepare();
@Override
public void run() {
try {
prepare();
prepareDone = true;
} catch (Exception e) {
prepareDone = false;
} finally {
if (countDownLatch != null) {
countDownLatch.countDown();
}
}
}
public String getPrepareName() {
return prepareName;
}
public boolean isPrepareDone() {
return prepareDone;
}
}
抽象类
实现类1: 模拟数据准备(后面2,3类似,只是成员变量简单变化)
public class DataPreparer extends BasePreparer {
public DataPreparer(CountDownLatch countDownLatch) {
super("data prepare", countDownLatch);
}
@Override
protected void prepare() {
System.out.println(this.getPrepareName() + "is doing");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(this.getPrepareName() + "is done");
}
}
实现类1
实现类2: 模拟网络准备
public class NetworkPreparer extends BasePreparer {
public NetworkPreparer(CountDownLatch countDownLatch) {
super("network prepare", countDownLatch);
}
@Override
protected void prepare() {
System.out.println(this.getPrepareName() + "is doing");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(this.getPrepareName() + "is done");
}
}
实现类2
实现类3: 模拟资源准备
public class ResourcePreparer extends BasePreparer {
public ResourcePreparer(CountDownLatch countDownLatch) {
super("resource prepare", countDownLatch);
}
@Override
protected void prepare() {
System.out.println(this.getPrepareName() + "is doing");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(this.getPrepareName() + "is done");
}
}
实现类3
主调用类
public class CountDownLatchMain {
private static final int LATCH_NUMBER = 3;
public static void main(String[] args) throws InterruptedException {
List<BasePreparer> preparerList = Lists.newArrayListWithExpectedSize(LATCH_NUMBER);
CountDownLatch countDownLatch = new CountDownLatch(LATCH_NUMBER);
preparerList.add(new ResourcePreparer(countDownLatch));
preparerList.add(new DataPreparer(countDownLatch));
preparerList.add(new NetworkPreparer(countDownLatch));
ExecutorService executorService = Executors.newFixedThreadPool(LATCH_NUMBER);
preparerList.forEach(executorService::execute);
countDownLatch.await();
List<BasePreparer> readyList = preparerList.stream().filter(BasePreparer::isPrepareDone).collect(Collectors.toList());
System.out.println(readyList.size() == LATCH_NUMBER);
}
}
主调用类
运行结果
resource prepareis doing
network prepareis doing
data prepareis doing
network prepareis done
data prepareis done
resource prepareis done
true
运行结果
「java.util.concurrent并发包」之 CountDownLatch的更多相关文章
- 「java.util.concurrent并发包」之 ThreadPoolExecutor
一 异步用new Thread? 大写的"low"!! new Thread(new Runnable() { @Override public void run() { // T ...
- 「java.util.concurrent并发包」之 CopyOnWrite
一 CopyOnWrite容器概述 Copy-On-Write简称COW,是一种用于程序设计中的优化策略.其基本思路是,从一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容C ...
- 「java.util.concurrent并发包」之 ReentrantReadWriteLock
一 引言 在多线程的环境下,对同一份数据进行读写,会涉及到线程安全的问题.比如在一个线程读取数据的时候,另外一个线程在写数据,而导致前后数据的不一致性:一个线程在写数据的时候,另一个线程也在写,同样也 ...
- 「java.util.concurrent并发包」之 CAS
一 引言 在JDK 5之前Java语言是靠synchronized关键字保证同步的,这会导致有锁 锁机制存在以下问题: (1)在多线程竞争下,加锁.释放锁会导致比较多的上下文切换和调度延时,引起性能 ...
- 「java.util.concurrent并发包」之 CyclicBarrier
一 描述 CyclicBarrier初始化时规定一个数目,然后计算调用了CyclicBarrier.await()进入等待的线程数.当线程数达到了这个数目时,所有进入等待状态的线程被唤醒并继续.Cyc ...
- Java并发:多线程和java.util.concurrent并发包总结
多线程和java.util.concurrent并发包 转载:
- Java并发—java.util.concurrent并发包概括(转载)
一.描述线程的类:Runable和Thread都属于java.lang包 二.内置锁synchronized属于jvm关键字,内置条件队列操作接口Object.wait()/notify()/noti ...
- java.util.concurrent并发包诸类概览
java.util.concurrent包的类都来自于JSR-166:Concurrent Utilities,官方的描述叫做“The JSR proposes a set of medium-lev ...
- java多线程---------java.util.concurrent并发包----------等待多线程完成
一.等待多线程完成的join的使用.CoundownLantch.CyclicBarrier .
随机推荐
- 深度学习笔记(十三)YOLO V3 (Tensorflow)
[代码剖析] 推荐阅读! SSD 学习笔记 之前看了一遍 YOLO V3 的论文,写的挺有意思的,尴尬的是,我这鱼的记忆,看完就忘了 于是只能借助于代码,再看一遍细节了. 源码目录总览 tens ...
- neo4j︱与python结合的py2neo使用教程
—- 目前的几篇相关:—– neo4j︱图数据库基本概念.操作罗列与整理(一) neo4j︱Cypher 查询语言简单案例(二) neo4j︱Cypher完整案例csv导入.关系联通.高级查询(三) ...
- elastic search&logstash&kibana 学习历程(四)kibana安装部署和使用
kibana在linux上的部署安装 运行环境是centos7 基于jdk8 下载安装包:wget https://artifacts.elastic.co/downloads/kibana/kiba ...
- webpack4 打包 library 遇到的坑
output: { publicPath: '/', path: path.join(__dirname, 'lib'), filename: 'chart.js', library: 'tchart ...
- Linux设备驱动程序 之 并发及其管理
竞态产生 Linux系统找那个存在大量的并发联系,因此会导致可能的竞态: 1. 正在运行的用户空间进程可以以多种组合方式访问我们的代码: 2. SMP系统甚至可以再不同的处理器上同时执行我们的代码: ...
- kafka可视化工具安装及简单使用
一.安装 双击kafkatool_64bit.exe安装kafka可视化工具,并且C:\Windows\System32\drivers\etc配置HOSTS,打开HOSTS并添加: HOSTS添加: ...
- 小马哥-Java 微服务实践 - Spring Boot 系列-01Java 微服务实践 - Spring Boot 系列(一)初体验
课程github地址 https://github.com/mercyblitz/segmentfault-lessons 传统的web应用架构.微服务是一种架构.不限定什么语言 单体应用和微服务的对 ...
- 你应该知道的 MySQL 的锁
背景 数据库的锁是在多线程高并发的情况下用来保证数据稳定性和一致性的一种机制.MySQL 根据底层存储引擎的不同,锁的支持粒度和实现机制也不同.MyISAM 只支持表锁,InnoDB 支持行锁和表锁. ...
- ceph对接openstack环境(4)
ceph对接openstack环境 环境准备: 保证openstack节点的hosts文件里有ceph集群的各个主机名,也要保证ceph集群节点有openstack节点的各个主机名 一.使用rbd方式 ...
- 在SuSE安装wifidog认证服务器和网关
在SuSE安装认证服务器和网关 在openSuSE 10.3安装wifidog 认证服务器和网关在同台设备中安装完毕.以下是openSuSE的详细安装指南.这个安装是非常初级的,所以请验证或更正. - ...