CountDownLatch是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待 ,即CountDownLatch允许一个或多个线程等待其他线程完成操作。闭锁可以延迟线程的进度直到其到达终止状态,闭锁可以用来确保某些活动直到其他活动都完成才继续执行。

文章目录

  • CountDownLatch简介
  • CountDownLatch方法
  • CountDownLatch图示
  • CountDownLatch实例
    • 代码实现
    • 运行结果
  • 源码解读
  • 本文小结

CountDownLatch简介

在多线程协作完成业务功能时,有时候需要等待其他多个线程完成任务之后,主线程才能继续往下执行业务功能,在这种的业务场景下,通常可以使用Thread类的join方法,让主线程等待被join的线程执行完之后,主线程才能继续往下执行。当然,使用线程间消息通信机制也可以完成。其实,Java并发工具类中为我们提供了类似“倒计时”这样的工具类,可以十分方便的完成所说的这种业务场景。

CountDownLatch类似计数器的功能,CountDownLatch是一种灵活的闭锁实现,能够使一个线程在等待另外一些线程完成各自工作之后,再继续执行。使用一个计数器进行实现。计数器初始值为线程的数量。当每一个线程完成自己任务后,计数器的值就会减一。当计数器的值为0时,表示所有的线程都已经完成了任务,然后在CountDownLatch上等待的线程就可以恢复执行任务。


CountDownLatch方法

JDK1.8中CountDownLatch方法如下.

先从CountDownLatch的构造方法看起

public CountDownLatch(int count)

构造方法会传入一个整型数N,之后调用CountDownLatch的countDown方法会对N减一,直到N减到0的时候,当前调用await方法的线程才继续执行。

CountDownLatch的方法不是很多,将它们一个个列举出来

  1. await() throws InterruptedException:调用该方法的线程等到构造方法传入的N减到0的时候,才能继续往下执行;
  2. await(long timeout, TimeUnit unit):与上面的await方法功能一致,只不过这里有了时间限制,调用该方法的线程等到指定的timeout时间后,不管N是否减至为0,都会继续往下执行;
  3. countDown():使CountDownLatch初始值N减1;
  4. long getCount():获取当前CountDownLatch维护的值;

CountDownLatch图示

CountDownLatch图示


CountDownLatch实例

面试题实现一个容器,提供两个方法,一个size读,一个add写两个线程,线程1往自定义容器中添加十个元素,线程2实时监控容器中的数量,在容器中元素个数为5的时候输出并结束线程使用门闩,门闩初始为1,当变为0的时候门闩打开,线程2就受到了通知,输出并结束


代码实现

package wideth.util;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;public class MyCountDownLatch {private volatile List<Object> list = new ArrayList<>();private void add(Object o) {list.add(o);}private int size() {return list.size();}public static void main(String[] args) {CountDownLatch latch = new CountDownLatch(1);MyCountDownLatch container = new MyCountDownLatch();// 自定义的容器new Thread(() -> {if (container.size() != 5) {try {latch.await();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("thread2 - end");}).start();new Thread(() -> {for (int i = 0; i < 10; i++) {if (container.size() == 5) {latch.countDown();}try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("thread1 - add");container.add(new Object());}}).start();}
}

运行结果

代码分析

CountDownLatch的构造函数接收一个int类型的参数作为计数器,如果你想等待N个点完成,这里就传入N。当我们调用CountDownLatch的countDown方法时,N就会减1,CountDownLatch的await方法会阻塞当前线程,直到N变成零。

由于countDown方法可以用在任何地方,所以这里说的N个点,可以是N个线程,也可以是1个线程里的N个执行步骤。用在多个线程时,只需要把这个CountDownLatch的引用传递到线程里即可。


源码解读

CountDownLatch 基于 AQS 的共享模式的使用

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;public class CountDownLatch {private final Sync sync;    // 同步器/*** 同步计数器的构造方法,传入计数总量*/public CountDownLatch(int count) {if (count < 0) throw new IllegalArgumentException("count < 0");this.sync = new Sync(count);}/*** 等待计数等于0,如果不为0则进入中断状态*/public void await() throws InterruptedException {sync.acquireSharedInterruptibly(1);}/*** 规定时间内 等待计数等于0,如果不为0则进入中断状态* @param timeout 最长等待时间* @param unit 时间单位,例如传入TimeUnit.SECONDS* @throws InterruptedException*/public boolean await(long timeout, TimeUnit unit)throws InterruptedException {return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));}/*** 递减锁计数* 如果减到0调用则什么都不会发生*/public void countDown() {sync.releaseShared(1);}/*** 返回当前计数*/public long getCount() {return sync.getCount(); // 实际上最终调用aqs的getState方法}/*** 返回计数信息的字符串*/public String toString() {return super.toString() + "[Count = " + sync.getCount() + "]";}/*** 同步控制计数器*/private static final class Sync extends AbstractQueuedSynchronizer {private static final long serialVersionUID = 4982264981922014374L;Sync(int count) {setState(count); // 给aqs设置state值}int getCount() {return getState(); // 调用aqs中的方法得到state值}protected int tryAcquireShared(int acquires) {return (getState() == 0) ? 1 : -1;}protected boolean tryReleaseShared(int releases) {// 递减计数,直到计数等于0返回for (;;) {int c = getState();//获取state值if (c == 0)return false;// 返回int nextc = c - 1;if (compareAndSetState(c, nextc)) // 将计数器更新return nextc == 0;}}}
}

本文小结

CountDownLatch闭锁,中文也可以翻译成门闩,倒计时器等,本文介绍了CountDownLatch的基本概念,应用场景以及实例分析,最后解读了源码。

同步工具之CountDownLatch闭锁相关推荐

  1. 14、详解java同步工具类CountDownLatch

    这篇文章主要讲解java中一个比较常用的同步工具类CountDownLatch,不管是在工作还是面试中都比较常见.我们将通过案例来进行讲解分析. 一.定义 CountDownLatch的作用很简单,就 ...

  2. JAVA同步工具类——CountDownLatch

    闭锁 在学习CountDownLatch之前,让我们先了解一下闭锁的概念. 闭锁是一种同步工具类,可以延迟线程的进度直到其到达终止状态:闭锁的作用相当于一扇门,在闭锁到达结束状态之前,这扇门一直是关闭 ...

  3. java并发基础(二)--- Java监视器模型、并发容器、同步工具类(闭锁、信号量)

    原blog链接:http://www.cnblogs.com/peterxiao/p/6921903.html 总结一下第4.5章的东西. 一.java监视器模式 概念:把对象的所有可变状态都封装起来 ...

  4. 并发编程-16AQS同步组件之CountDownLatch 闭锁

    文章目录 脑图 CountDownLatch闭锁 示例 Thread#join() CountDownLatch CountDownLatch示例二 await一直等待其他线程执行完 CountDow ...

  5. 深入分析同步工具类之AbstractQueuedSynchronizer

    概览: AQS(简称)依赖内部维护的一个FIFO(先进先出)队列,可以很好的实现阻塞.同步:volatile修饰的属性state,哪个线程先改变这个状态值,那么这个线程就获得了优先权,可以做任何事(当 ...

  6. Java 并发编程之同步工具类闭锁 CountDownLatch

    Java 同步工具类CountDownLatch相当于一个计数器,假设一个方法,等待一个计数器从初始值5变为0,每使用一次countdown()方法,计数器的值减少1,当计数器的值为0时,触发某件事. ...

  7. Java并发中常用同步工具类

    为什么80%的码农都做不了架构师?>>>    同步工具类可以是任何一个对象,只要它根据其自身的状态来协调线程控制流.阻塞队列(BlockingQueue)可以作为同步工具类,其他类 ...

  8. java多线程并发之旅-20-同步工具类。闭锁/栅栏/信号量/阻塞队列/FutureTask

    同步工具类 同步工具类主要包括闭锁(如CountDownLatch),栅栏(如CyclicBarrier),信号量(如Semaphore)和阻塞队列(如LinkedBlockingQueue)等: F ...

  9. Java并发工具类(闭锁CountDownLatch)

    并发工具类系列: Java并发工具类(闭锁CountDownLatch) Java并发工具类(栅栏CyclicBarrier) Java并发工具类(信号量Semaphore) 闭锁是一种同步工具类,可 ...

最新文章

  1. 知乎热议:国家何时整治程序员的高薪现象?网友:用命和头发换的钱都被人眼红!...
  2. 解决Windows Installer的错误
  3. POJ 2417 Discrete Logging 离散对数
  4. 使用命令创建mysql_用命令创建MySQL数据库
  5. [Issue Fixed]-GCC编译[-Werror,-Wformat]
  6. 按应用领域来划分,电话光端机主要分为哪几类
  7. EASYUI+MVC4通用权限管理平台
  8. “堂堂985博士,要去高职了,天空是灰暗的!!!”
  9. php 获取视频首帧,从视频中提取特定帧的最快方法(PHP/ffmpeg/anything)
  10. vant 项目_基于 vue3.x+vant3.x 搭建示例项目
  11. 2022-07-17 mysql使用的flex/yacc语法练习
  12. 计算机硬件性能检测报告,性能测试实验报告.doc
  13. wgs84转cgcs2000 java_CGCS2000坐标系与WGS84的相互投影转换
  14. SystemGenerator:数字信号处理之开发准备、流程预演
  15. QQ邮箱服务器协议,理解邮件服务流程——SMTP、IMAP、POP3 协议
  16. PC端浏览器定位(纯前端)
  17. SSL-ZYC 最小步数
  18. 使用网页操作助手制作自己的火车票抢票工具
  19. 数据结构 —— 队列、栈、链表的区别
  20. 如何解决WIN10处于通知模式的问题?

热门文章

  1. 负载均衡集群HAProxy安装篇
  2. Linux 6.5选包截图
  3. 【IPC通信】匿名管道
  4. AgileEAS.NET平台开发Step By Step系列-药店系统-索引
  5. PS教程:如何批量处理图片
  6. set、vector与list的构造与排序的耗时测试
  7. ConfirmCancelUtilDialog【确认取消对话框封装类】
  8. Python 更新set
  9. Android访问php webservice
  10. 安装nagios_grapher,有图有真相。