【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 ...
随机推荐
- CDH6.2.0 搭建大数据集群
1. 资料准备 现在官网https://www.cloudera.com 需要注册账号,未来可能会收费等问题,十分麻烦,这里有一份我自己百度云的备份 链接: https://pan.baidu.com ...
- [Qt基础内容-08] Qt中MVC的M(Model)
Qt中MVC的M(Model)简单介绍 Qt有自己的MVC框架,分别是model(模型).view(视图).delegate(委托),这篇文章,简单的介绍以下Qt中有关model(模型)的类以及一些基 ...
- 使用 Spring Boot Admin 监控应用状态
程序员优雅哥 SpringBoot 2.7 实战基础 - 11 - 使用 Spring Boot Admin 监控应用状态 1 Spring Boot Actuator Spring Boot Act ...
- 硬核剖析Redis单线程为什么那么快?
(本文首发于"数据库架构师"公号,订阅"数据库架构师"公号,一起学习数据库技术,助力职业发展) Redis目前是使用率最高的内存库数据库,是企业应用开发的必备, ...
- 【疑难杂症】if __name__ == '__main__'的理解
今天进行小批量梯度下降时,代码给我报错,具体代码如下 import torch import numpy as np from torch.utils.data import Dataset from ...
- WPF绘制圆形调色盘
本文使用writeableBitmap类和HSB.RGB模式来绘制圆形的调色盘. 开源项目地址:https://github.com/ZhiminWei/Palette RGB为可见光波段三个颜色通道 ...
- 关于aws-Lambda的cron周期性计划任务-表达式的定义方式
关于aws-Lambda的cron周期性定时任务的定义方式,与其他系统或者语言可能略有差异 区别之一,就是Lambda是6个字段的, (分,时,日,月,周,年),多了一个年份字段,各字段之间使用空格隔 ...
- redis bitmap数据结构之java对等操作
在之前的文章中,我们有说过bitmap,bitmap在很多场景可以应用,比如黑白名单,快速判定,登录情况等等.总之,bitmap是以其高性能出名.其基本原理是一位存储一个标识,其他衍生知道咱就不说了, ...
- bean文档类型定义
ELEMENT:表示当前 (bean*):表示0到多个bean元素 (property*):表示0到多个property元素 ATTLIST:表示属性 #REQUIRED:表示不可缺少 #IMPLIE ...
- 『现学现忘』Git基础 — 36、标签tag(一)
目录 1.标签介绍 2.列出标签 3.创建标签 (1)标签的分类 (2)附注标签 (3)轻量标签 4.后期打标签 1.标签介绍 软件的某个发行版本所对应的,其实就是软件开发过程中,某一个阶段的最后一次 ...