【Java并发010】使用层面:发令枪CountDownLatch全解析
一、前言
CountDownLatch是在java1.5被引入,存在于java.util.cucurrent包中,跟它一起被引入的工具类还有CyclicBarrier、Semaphore、concurrentHashMap和BlockingQueue。
二、CountDownLatch概要
CountDownLatch类作用:使一个线程等待其他线程各自执行完毕后再执行。
CountDownLatch三步操作
- 构造函数:它是通过一个计数器来实现的,计数器的初始值是线程的数量;
- 减一操作:每当一个线程执行完毕后,计数器的值就-1;
- 阻塞通过:当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。
CountDownLatch发令枪的意义:让所有线程启动后一起执行,不会先启动的先执行。
CountDownLatch发令枪的实现:构造函数确定数量、countDown减一操作、await全部为0发令启动。
三、CountDownLatch源码解析
CountDownLatch类中只提供了一个构造器:
//参数count为计数值
public CountDownLatch(int count) { };
类中有三个方法是最重要的:
//调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行
public void await() throws InterruptedException { };
//和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行
public boolean await(long timeout, TimeUnit unit) throws InterruptedException { };
//将count值减1
public void countDown() { };
小结,一定要调用的方法是:构造函数、countDown、await。
四、CountDownLatch普通示例(涉及的方法:构造函数、countDown、await)
public class CountDownLatchTest {
public static void main(String[] args) {
final CountDownLatch latch = new CountDownLatch(2); // 初始数量为2
System.out.println("主线程开始执行…… ……");
//第一个子线程执行
ExecutorService es1 = Executors.newSingleThreadExecutor();
es1.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
System.out.println("子线程:"+Thread.currentThread().getName()+"执行");
} catch (InterruptedException e) {
e.printStackTrace();
}
latch.countDown();
}
});
es1.shutdown();
//第二个子线程执行
ExecutorService es2 = Executors.newSingleThreadExecutor();
es2.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程:"+Thread.currentThread().getName()+"执行");
latch.countDown();
}
});
es2.shutdown();
System.out.println("等待两个线程执行完毕…… ……");
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("两个子线程都执行完毕,继续执行主线程");
}
}
运行结果:
主线程开始执行…… ……
等待两个线程执行完毕…… ……
子线程:pool-1-thread-1执行
子线程:pool-2-thread-1执行
两个子线程都执行完毕,继续执行主线程
五、CountDownLatch并发示例(涉及的方法:构造函数、countDown、await)
public class Parallellimit {
public static void main(String[] args) {
ExecutorService pool = Executors.newCachedThreadPool();
CountDownLatch cdl = new CountDownLatch(100);
for (int i = 0; i < 100; i++) {
CountRunnable runnable = new CountRunnable(cdl); // 设置CountRunnable类中countDownLatch变量的数据为100
pool.execute(runnable);
}
}
}
class CountRunnable implements Runnable {
private CountDownLatch countDownLatch;
public CountRunnable(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
try {
synchronized (countDownLatch) {
/*** 每次减少一个容量*/
countDownLatch.countDown();
System.out.println("thread counts = " + (countDownLatch.getCount()));
}
countDownLatch.await();
System.out.println("concurrency counts = " + (100 - countDownLatch.getCount()));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行结果:
thread counts = 99
thread counts = 98
thread counts = 97
thread counts = 96
thread counts = 95
thread counts = 94
......
thread counts = 6
thread counts = 5
thread counts = 4
thread counts = 3
thread counts = 2
thread counts = 1
thread counts = 0
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
CountDownLatch和CyclicBarrier区别:
- countDownLatch是一个计数器,线程完成一个记录一个,计数器递减,只能只用一次
- CyclicBarrier的计数器更像一个阀门,需要所有线程都到达,然后继续执行,计数器递增,提供reset功能,可以多次使用
六、面试金手指
6.1 CountDownLatch
countDownLatch定义:使一个线程等待其他线程各自执行完毕后再执行。
countDownLatch一定要调用的方法: 构造函数、countDown、await
- 构造函数中确定数量
- countDown减一操作
- await一定要等到构造函数中设置的count=0才放开阻塞
发令枪CountDownLatch的意义:让所有线程启动后一起执行,不会先启动的先执行。
发令枪CountDownLatch的实现:构造函数确定数量、countDown减一操作、await全部为0发令启动
6.2 面试问题:如何控制十个线程依次输出1~10?
问题:如何控制十个线程依次输出1~10?
回答:
- 联合线程,join,线程嵌套的方式;
- 线程通信,synchronized+标志位+wait()+notify()/notifyAll() 或者 lock锁+标志位+condition.await()+condition.signal()/signalAll()
七、小结
使用层面:发令枪CountDownLatch全解析,完成了。
天天打码,天天进步!!!
【Java并发010】使用层面:发令枪CountDownLatch全解析的更多相关文章
- [Java并发] AQS抽象队列同步器源码解析--锁获取过程
要深入了解java并发知识,AbstractQueuedSynchronizer(AQS)是必须要拿出来深入学习的,AQS可以说是贯穿了整个JUC并发包,例如ReentrantLock,CountDo ...
- [Java并发] AQS抽象队列同步器源码解析--独占锁释放过程
[Java并发] AQS抽象队列同步器源码解析--独占锁获取过程 上一篇已经讲解了AQS独占锁的获取过程,接下来就是对AQS独占锁的释放过程进行详细的分析说明,废话不多说,直接进入正文... 锁释放入 ...
- Java并发编程总结(一)Syncronized解析
Syncronized解析 作用: )确保线程互斥的访问同步代码 )保证共享变量的修改能够及时可见 )有效解决重排序问题. 用法: )修饰普通方法(锁是当前实例对象) )修饰静态方法(锁是当前对象的C ...
- Java并发编程(六)volatile关键字解析
由于volatile关键字是与Java的内存模型有关的,因此在讲述volatile关键之前,我们先来了解一下与内存模型相关的概念和知识. 一.内存模型的相关概念 Java内存模型规定所有的变量都是存在 ...
- JAVA并发编程之倒计数器CountDownLatch
CountDownLatch 的使用场景:在主线程中开启多线程去并行执行任务,并且主线程需要等待所有子线程执行完毕后汇总返回结果. 我把源码中的英文注释全部删除,写上自己的注释.就剩下 70 行不到的 ...
- Java并发(8):CountDownLatch、CyclicBarrier、Semaphore、Callable、Future
CountDownLatch.CyclicBarrier.Semaphore.Callable.Future 都位于java.util.concurrent包下,其中CountDownLatch.C ...
- Java并发编程:Semaphore、CountDownLatch、CyclicBarrier
首先我们来实现一个功能:当我们启动一个系统的时候需要初始化许多数据,这时候我们可能需要启动很多线程来进行数据的初始化,只有这些系统初始化结束之后才能够启动系统.其实在Java的类库中已经提供了Sema ...
- Java并发编程_wait/notify和CountDownLatch的比较(三)
1.wait/notify方法 package sync; import java.util.ArrayList; import java.util.List; public class WaitA ...
- 【Java并发编程】6、volatile关键字解析&内存模型&并发编程中三概念
volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在Java 5之后,volatile关键字才得以 ...
- Java 最常见 200+ 面试题答案全解析-面试必备
本文分为十九个模块,分别是: Java 基础.容器.多线程.反射.对象拷贝.Java Web .异常.网络.设计模式.Spring/Spring MVC.Spring Boot/Spring Clou ...
随机推荐
- KDB_Database_Link 使用介绍
kdb_database_link 是 KingbaseES 为了兼容oracle 语法而开发的跨数据库访问扩展,可用于访问KingbaseES, Postgresql , Oracle .以下分别介 ...
- [Python]-sklearn模块-机器学习Python入门《Python机器学习手册》-02-加载数据:加载数据集
<Python机器学习手册--从数据预处理到深度学习> 这本书类似于工具书或者字典,对于python具体代码的调用和使用场景写的很清楚,感觉虽然是工具书,但是对照着做一遍应该可以对机器学习 ...
- 对比es6class类和构造函数
构造函数 在原来class 类这个语法糖没有出来之前 我们一般会把方法挂在prototype 上 为了防止过多的开辟内存 1 // 构造函数------------------------------ ...
- 新开源HTML5单文件网页版ACME客户端,可在线申请Let's Encrypt、ZeroSSL免费HTTPS多域名通配符泛域名SSL/TLS证书(RSA/ECC/ECDSA)
目录 开源项目的起源 项目地址 使用方法 第一步:选择Let's Encrypt.ZeroSSL或其他证书颁发机构 第二步:证书配置,填写域名 第三步:完成域名所有权的验证 第四步:下载保存证书PEM ...
- Pod 使用进阶
静态 Pod 在 Kubernetes 集群中除了我们经常使用到的普通的 Pod 外,还有一种特殊的 Pod,叫做Static Pod,也就是我们说的静态 Pod,静态 Pod 有什么特殊的地方呢? ...
- 4.Ceph 基础篇 - 对象存储使用
文章转载自:https://mp.weixin.qq.com/s?__biz=MzI1MDgwNzQ1MQ==&mid=2247485256&idx=1&sn=39e07215 ...
- MySQL手动恢复数据库测试操作
事件背景 MySQL数据库每日零点自动全备 某天上午9点,二狗子不小心drop了一个数据库 我们需要通过全备的数据文件,以及增量的binlog文件进行数据恢复 主要思想与原理 利用全备的sql文件中记 ...
- docker相关总结
Docker 的相关使用记录 一.安装docker linux环境使用yum命令安装docker 第一步:确保自己的虚拟机没有安装过docker,如果安装过的需要将原先的docker进行卸载,命令如下 ...
- 复现禅道V16.5的SQL注入(CNVD-2022-42853)
漏洞详情 禅道V16.5未对输入的account参数内容作过滤校验,导致攻击者拼接恶意SQL语句执行. 环境搭建 环境下载:禅道V16.5 下载后双击运行,进入目录运行start.exe 直接访问即可 ...
- 2_JDBC
一. 引言 1.1 如何操作数据库 使用客户端工具访问数据库, 需要手工建立连接, 输入用户名和密码登陆, 编写SQL语句, 点击执行, 查看操作结果(结果集或受行数影响) 1.2 实际开发中, 会采 ...