CountDownLatch(三)
CountDownLatch简介
(1)用于解决什么问题?
在并发编程的场景中,最常见的一个case是某个任务的执行,需要等到多个线程都执行完毕之后才可以进行,CountDownLatch可以很好解决这个问题。
(2)使用说明
同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。
(3)CountDownLatch的常用方法
1.构造方法:
// 构造器,必须指定一个大于零的计数
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
// Sync 就是继承了一个AQS
this.sync = new Sync(count);
}
2.await方法
// 线程阻塞,直到计数为0的时候唤醒;可以响应线程中断退出阻塞
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
// 线程阻塞一段时间,如果计数依然不是0,则返回false;否则返回true
public boolean await(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
await内部实现流程:
- 判断state计数是否为0,不是,则直接放过执行后面的代码;
- 大于0,则表示需要阻塞等待计数为0;
- 当前线程封装Node对象,进入阻塞队列;
- 然后就是循环尝试获取锁,直到成功(即state为0)后出队,继续执行线程后续代码。
await是通过轮询state的状态来判断所有的任务是否都完成。
3.countDown方法
// 计数-1
public void countDown() {
sync.releaseShared(1);
}
countDown内部实现流程:
- 尝试释放锁tryReleaseShared,实现计数-1
- 若计数已经小于0,则直接返回false;
- 否则执行计数(AQS的state)减一;
- 若减完之后,state==0,表示没有线程占用锁,即释放成功,然后就需要唤醒被阻塞的线程了;
- 释放并唤醒阻塞线程 doReleaseShared;
- 如果队列为空,即表示没有线程被阻塞(也就是说没有线程调用了 CountDownLatch#wait()方法),直接退出;
- 头结点如果为SIGNAL, 则依次唤醒头结点下个节点上关联的线程,并出队;
4.getCount方法
// 获取计数
public long getCount() {
return sync.getCount();
}
(4)小例子:计算多个线程并发运行的时间。
public class TestCountDownLatch {
public static void main(String[] args) throws InterruptedException {
long start = System.currentTimeMillis();
CountDownLatch countDownLatch = new CountDownLatch(5);
CountDownLatchThread countDownLatchThread = new CountDownLatchThread(countDownLatch);
for (int i = 0; i < 5; i++){
new Thread(countDownLatchThread).start();
}
// 主线程等待
countDownLatch.await();
long end = System.currentTimeMillis();
System.out.println("time : " + (end - start));
}
}
class CountDownLatchThread implements Runnable{
private CountDownLatch countDownLatch = null;
public CountDownLatchThread(CountDownLatch countDownLatch){
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
synchronized (this){
// 加入try确保countDownLatch.countDown()一定会执行
try {
for (int i = 0; i < 10; i++){
System.out.println(Thread.currentThread().getName() + " : " + i);
}
}finally {
countDownLatch.countDown();
}
}
}
}
参考文献
本片文章,主要整理自互联网,便于自己复习知识所用,以下为参考链接!
【1】Java并发学习之CountDownLatch实现原理及使用姿势
CountDownLatch(三)的更多相关文章
- 多线程辅助类之CountDownLatch(三)
CountDownLatch信号灯是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待.它可以实现多线程的同步互斥功能,和wait和notify方法实现功能类似,具体 ...
- Java Thread系列(四)线程通信
Java Thread系列(四)线程通信 一.传统通信 public static void main(String[] args) { //volatile实现两个线程间数据可见性 private ...
- 多线程辅助类之CyclicBarrier(四)
CyclicBarrier是一个线程辅助类,和<多线程辅助类之CountDownLatch(三)>功能类似,都可以实现一组线程的相互等待.要说不通点,那就是CyclicBarrier在释放 ...
- 并发编程(三):从AQS到CountDownLatch与ReentrantLock
一.目录 1.AQS简要分析 2.谈CountDownLatch 3.谈ReentrantLock 4.谈消费者与生产者模式(notfiyAll/wait.si ...
- Java并发编程_wait/notify和CountDownLatch的比较(三)
1.wait/notify方法 package sync; import java.util.ArrayList; import java.util.List; public class WaitA ...
- 带你看看Java的锁(三)-CountDownLatch和CyclicBarrier
带你看看Java中的锁CountDownLatch和CyclicBarrier 前言 基本介绍 使用和区别 核心源码分析 总结 前言 Java JUC包中的文章已经写了好几篇了,首先我花了5篇文章从源 ...
- 【Java并发核心三】CountDownLatch、CyclicBarrier及Phaser
个人感觉,看书学习还是需要“不求甚解”,因为一旦太过于计较小的得失,就容易钻牛角尖,学习进度也慢.我们完全可以先学一个大概,等到真正用到的时候再把那些细节丰富起来,就更有针对性. 所以,针对java并 ...
- Java并发编程原理与实战三十:CountDownLatch与CyclicBarrier 区别
相信每个想深入了解多线程开发的Java开发者都会遇到CountDownLatch和CyclicBarrier,大家也在网上看到各种介绍原理,代码的,以及他们区别(应付面试)的,但是很少能讲清楚:他们到 ...
- 多线程编程(三)-CountDownLatch的使用
CountDownLatch的介绍 类CountDownLatch是同步功能得一个辅助类,使用效果就是给定一个计数,当使用CountDownLatch类的线程判断计数不为0时,则呈wait状态,如果是 ...
随机推荐
- Maven之profile实现多环境配置动态切换
一般的软件项目,在开发.测试及生产等环境下配置文件中参数是不同的.传统的做法是在项目部署的时候,手动修改或者替换这个配置文件.这样太麻烦了,我们可以用Maven的profile来解决这 ...
- 【原创】自己动手写一个能操作redis的客户端
引言 redis大家在项目中经常会使用到.官网也提供了多语言的客户端供大家操作redis,如下图所示 但是,大家有思考过,这些语言操作redis背后的原理么?其实,某些大神会说 只要按照redis的协 ...
- 深入理解[Master-Worker模式]原理与技术
Master-Worker模式是常用的并行模式之一.它的核心思想是,系统由两类进程协作工作:Master进程和Worker进程.Master进程负责接收和分配任务,Worker进程负责处理子任务.当各 ...
- JVM规范系列开篇:为什么要读JVM规范?
许多人知道类加载机制.JVM内存模型,但他们可能不知道什么是<Java虚拟机规范>.对于Java开发来说,<Java虚拟机规范>才是最为官方.准确的一个文档,了解这个规范可以让 ...
- UART、SPI和I2C详解
做单片机开发时UART,SPI和I2C都是我们最经常使用到的硬件接口,我收集了相关的具体材料对这三种接口进行了详细的解释. UART UART是一种通用串行数据总线,用于异步通信.该总线双向通信,可以 ...
- python之psutil模块详解(Linux)--小白博客
Python-psutil模块 windows系统监控实例,查询 https://www.cnblogs.com/zhou2019/p/10567282.html 1.简单介绍 psutil是一个跨平 ...
- jenkins 插件介绍
1.jenkins 利用maven编译,打包,所需插件:Maven Integration: Maven集成插件这个插件提供了Jenkins和Maven的深度集成,无论是好还是坏:项目之间的自动触发取 ...
- iOS 10的两个坑
iOS 10出现白屏幕,其他机型不会. 一个bug 手机连上电脑,在电脑端的Safari里,看到了如下的错误: SyntaxError: Cannot declare a let variable t ...
- vuex的购物车效果 index.js
import Vue from 'vue'; import Vuex, { Store } from 'vuex'; import { stat } from 'fs'; Vue.use(Vuex); ...
- vscode开发中绝对让你惊艳的插件!!!(个人在用)
识别模版引擎 1.Apache Velocity :识别Velocity(vm) 2.Art Template Helper:识别artTemplate 点击路径跳转 1.Laravel goto v ...