CountDownLatch 的用法

2023-05-16

CountDownLatch 的用法

    • 方法
      • 构造方法 CountDownLatch(int count)
      • countDown()
      • long getCount()
      • await()
      • boolean await(long timeout, TimeUnit unit)
    • 两个示例

CountDownLatch是一个同步工具类,它使用给定的 count初始化, await()方法会一直阻塞,直到计数器的值变为零(由于 countDown()方法被调用导致的),这时会释放所有等待的线程,且之后再调用 await()方法会直接返回,不会阻塞。 CountDownLatch是一个 一次性的类,计数器不能被重置,这一点与 CyclicBarrier不同。另一个不同点是: CountDownLatch是让所有线程 等待计数器的值变为零再继续执行;而 CyclicBarrier是要 等待指定个数的线程到达 Barrier 的位置再一起继续执行。

方法

构造方法 CountDownLatch(int count)

计数器的初始值为count,也就是说countDown()方法至少被调用count次等待的线程才会被唤醒。如果count为负数或抛出异常IllegalArgumentException

countDown()

如果当前计数器的值大于零,则将其减一,如果新的计数器值等于零,则释放所有等待的线程。
如果当前计数器为零,则什么都不做。
此方法不会阻塞。

long getCount()

获取当前计数器的值。

public static void test() throws InterruptedException {
	CountDownLatch cdl = new CountDownLatch(3);
	System.out.println(cdl.getCount());
	cdl.countDown();
	System.out.println(cdl.getCount());
	cdl.countDown();
	System.out.println(cdl.getCount());
	cdl.countDown();
	System.out.println(cdl.getCount());
	cdl.countDown();
	System.out.println(cdl.getCount());
	cdl.countDown();
	System.out.println(cdl.getCount());
}

计数器变为零后就不会再减了。

3
2
1
0
0
0

await()

导致当前线程等待,直到计数器的值变为零,除非线程被中断。如果计数器已经为零了,则立即返回。以下两种情况会抛出InterruptedException并清空中断标志:

  • 在调用wait()方法前,当前线程的中断状态已经为 true 了
  • 在等待的过程中被中断了

模拟两种中断情况

// 在调用`wait()`方法前,当前线程的中断状态已经为 true 了
public static void test1() throws InterruptedException {
	CountDownLatch cdl = new CountDownLatch(1);
	Thread.currentThread().interrupt();
	cdl.await();
}

// 在等待的过程中被中断了
public static void test2() throws InterruptedException {
	CountDownLatch cdl = new CountDownLatch(1);
	Thread t1 = new Thread(() -> {
		try {
			cdl.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}, "t1");
	t1.start();
	Thread.sleep(500);
	t1.interrupt();
}

boolean await(long timeout, TimeUnit unit)

此方法与await()的不同点:

  • 此方法至多会等待指定的时间,超时后会自动唤醒,若 timeout 小于等于零,则不会等待
  • 次方法有 boolean 类型的返回值:若计数器变为零了,则返回 true;若指定的等待时间过去了,则返回 false

等待指定时间

public static void test3() throws InterruptedException {
	CountDownLatch cdl = new CountDownLatch(1);
	log.info("开始 await");
	boolean b = cdl.await(2, TimeUnit.SECONDS);
	log.info("结束 await, 返回值: {}", b);
}

等待 2 秒后返回了,且返回值为 false

16:33:11.492 [main] INFO com.example.heima.concurrent.CountDownLatchTest - 开始 await
16:33:13.503 [main] INFO com.example.heima.concurrent.CountDownLatchTest - 结束 await, 返回值: false

计数器在等待过程中变为零

public static void test4() throws InterruptedException {
	CountDownLatch cdl = new CountDownLatch(1);
	Thread t1 = new Thread(() -> {
		try {
			log.info("开始 await");
			// 至多等待 2 秒
			boolean b = cdl.await(2, TimeUnit.SECONDS);
			log.info("结束 await, 返回值: {}", b);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}, "t1");
	t1.start();

	Thread.sleep(1000);
	cdl.countDown();
}

等待 1 秒后返回了,且返回值为 true

16:36:20.408 [t1] INFO com.example.heima.concurrent.CountDownLatchTest - 开始 await
16:36:21.421 [t1] INFO com.example.heima.concurrent.CountDownLatchTest - 结束 await, 返回值: true

计数器在调用await()方法前就变为 0 了

public static void test5() throws InterruptedException {
	CountDownLatch cdl = new CountDownLatch(1);
	cdl.countDown();
	log.info("开始 await");
	boolean b = cdl.await(2, TimeUnit.SECONDS);
	log.info("结束 await, 返回值: {}", b);
}

不会等待,且返回值为 true

16:38:33.047 [main] INFO com.example.heima.concurrent.CountDownLatchTest - 开始 await
16:38:33.054 [main] INFO com.example.heima.concurrent.CountDownLatchTest - 结束 await, 返回值: true

两个示例

以下代码均来源于源码的注释
Driver、Worker
下面是两个类,其中一组 Worker 线程使用了两个CountDownLatch

  • 第一个是启动信号,阻止任何 Worker 继续,直到 Driver 让他们继续
  • 第二个是完成信号,它允许 Driver 等待所有的 Worker 完成
class Driver { // ...
    public static void main(String[] args) throws InterruptedException {
        int N = 5;
        CountDownLatch startSignal = new CountDownLatch(1);
        CountDownLatch doneSignal = new CountDownLatch(N);

        for (int i = 0; i < N; ++i) // create and start threads
            new Thread(new Worker(startSignal, doneSignal)).start();

        System.out.println("doSomethingElse");          // don't let run yet
        startSignal.countDown();                        // let all threads proceed
        System.out.println("doSomethingElse");
        doneSignal.await();                             // wait for all to finish
        System.out.println("all worker completed");
    }
}

class Worker implements Runnable {
    private final CountDownLatch startSignal;
    private final CountDownLatch doneSignal;
    Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
        this.startSignal = startSignal;
        this.doneSignal = doneSignal;
    }
    public void run() {
        try {
            startSignal.await();
            doWork();
            doneSignal.countDown();
        } catch (InterruptedException ex) {} // return;
    }

    void doWork() {
        System.out.println("doWork");
    }
}

将一个问题分解为多个部分

class Driver2 { // ...
    public static void main(String[] args) throws InterruptedException {
        int N = 3;
        CountDownLatch doneSignal = new CountDownLatch(N);
        Executor e = Executors.newFixedThreadPool(N);
		
		// i 代表是问题的第几部分
        for (int i = 0; i < N; ++i) // create and start threads
            e.execute(new WorkerRunnable(doneSignal, i));

        doneSignal.await();           // wait for all to finish
        System.out.println("all task completed");
    }
}

class WorkerRunnable implements Runnable {
    private final CountDownLatch doneSignal;
    private final int i;
    WorkerRunnable(CountDownLatch doneSignal, int i) {
        this.doneSignal = doneSignal;
        this.i = i;
    }
    public void run() {
        doWork(i);
        doneSignal.countDown();
    }

    void doWork(int i) {
        System.out.println("task " + i);
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CountDownLatch 的用法 的相关文章

  • 正交编码器溢出处理

    文章目录 1 正交编码器1 1 参数特性1 2 应用范围 2 正交编码器使用2 1 溢出问题2 2 中断模式2 3 循环模式延伸 1 正交编码器 正交编码器一般指的是增量式光栅 xff08 磁栅 xff09 编码器 xff0c 通常有三路输
  • PX4多旋翼期望姿态矩阵生成算法

    1 PX4多旋翼期望姿态生成算法 1 1 求期望体轴X轴向量1 2 求期望体轴Y轴向量1 3 求期望姿态矩阵1 4 求期望姿态角 1 PX4多旋翼期望姿态生成算法 PX4多旋翼期望姿态生成采用旋转矩阵方法 xff0c 基本思路为根据外环解算
  • git安装

    Git介绍 分布式 xff1a Git版本控制系统是一个分布式的系统 xff0c 是用来保存工程源代码历史状态的命令行工具 保存点 xff1a Git的保存点可以追踪源码中的文件 并能得到某一个时间点上的整个工程项目的状态 xff1b 可以
  • linux更改ssh连接方式将publickey改为用户名密码登录

    1 vim etc ssh sshd config 2 PermitRootLogin no 改为 PermitRootLogin yes 3 service restart sshd
  • dsp2812 pmsm foc之速度环电流环

    61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 速度环PI 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
  • leetcode(c++)

    放假没事刷几道leetcode xff0c 一些常见典型题的答案和解析 平时python用的比较多 xff0c 但分析复杂度的时候用python编程不方便 xff0c 所以刷题的时候用了c 43 43 C 43 43 基础 C 43 43
  • 基于STM32的超声波雷达项目【可拟合构建平面地图】(代码开源)

    前言 xff1a 本文为手把手教学基于STM32的超声波雷达 项目 HC SR04雷达 本次项目采用的是STM32作为MCU xff0c 搭配常用的HC SR04超声波模块与舵机SG90实现模拟雷达检测 的效果 模拟了雷达图UI 可以拟合构
  • android sdk manager不显示更新,只显示已安装,解决办法

    启动 Android SDK Manager xff0c 打开主界面 xff0c 依次选择 Tools Options xff0c 弹出 Android SDK Manager Settings 窗口 xff1b 在 Android SDK
  • detectron2学习:KeyError: “No object named ‘XXXXX‘ found in ‘BACKBONE‘ registry!“

    问题来源 在使用FB的框架detectron2改写模型的时候碰到了KeyError 34 No object named 39 XXXXX 39 found in 39 BACKBONE 39 registry 34 的bug 分析 xff
  • linux内核网络协议栈--linux网络设备理解(十三)

    网络层次 linux网络设备驱动与字符设备和块设备有很大的不同 字符设备和块设备对应 dev下的一个设备文件 而网络设备不存在这样的设备文件 网络设备使用套接字socket访问 xff0c 虽然也使用read write系统调用 xff0c

随机推荐

  • makefile使用--命令(三)

    一 Make的概念 Make这个词 xff0c 英语的意思是 34 制作 34 Make命令直接用了这个意思 xff0c 就是要做出某个文件 比如 xff0c 要做出文件a txt xff0c 就可以执行下面的命令 span class t
  • 【笔记】ubuntu18.04 ros melodic turtlebot3 源码下,导航gmapping仿真

    编写本笔记原因 xff1a 源码编译没问题 xff0c 但是在运行roslaunch turtlebot3 slam turtlebot3 slam launch slam methods 61 cartgrapher时出现下面这个错误 x
  • 从kernel层面分析synchronized、volatile,进大厂必备硬核小伎俩(上)

    synchronized volatile对于java程序员来说再熟悉不过了 xff0c 但 是你知道这两个关键字底层是如何实现的吗 xff08 甚至在操作系层面是 通过什么指令来实现的 xff09 xff1f 以及与其相关的术语 xff1
  • linux内核原理剖析——内存寻址(一)

    最近总想分享点硬核的原创文章出来 xff0c 一是硬核技术是一个程序员真正应该修炼 的内功 xff1b 二是修炼硬核技能是通往架构师领域的必经之路 本系列文章将分享关 于linux内核设计原理相关的内容 xff0c 希望能打通我们的七经八脉
  • linux内核原理剖析——磁盘寻址、分区

    继上一篇 lt lt linux内核原理剖析 内存寻址 xff08 一 xff09 gt gt 之后 xff0c 发现大家 对底层技术关注度比较高之后 xff0c 今天继上一篇的内存寻址一文后 xff0c 补 充一篇关于更为底层的 磁盘寻址
  • Redis集群从搭建到设计,总有一些你不曾了解的东西

    Redis集群是Redis服务器高可用的设计模型 xff0c 也是我们线上应用最多的Redis部署架构 本文主要针对Redis集 群入门搭建 Redis集群节点及其底层数据结构 hash槽 重新分片 消息等核心操作及原理进行分享 本文是基于
  • java成神之路学习线路

    自己总结了下java后端学习线路 xff0c 也是我八年的工作学习积累 xff0c 供各位同学参考 线路图还不全 xff0c 之后我会逐渐补全 下面思维导图中的技术 xff0c 我争取在2020年的博文中都分享给大家 xff0c 形成一个系
  • 实时操作系统系统FreeRTOS的学习(1)——任务

    前言 xff1a 在本专栏 FreeRTOS 中已经为读者朋友详细介绍了FreeRTOS以及关于FreeRTOS于STM32下的手动移植 从今天开始将带领大家系统学习FreeRTOS xff0c 这款常见的轻量化小型 实时操作系统 当然 x
  • 万字博文,Spring系列之抽丝剥茧Spring源码(一)

    当5G来临 xff0c 当211高校已经开启人工智能课程 xff0c 当甲骨文大批量裁员 xff0c 大家的心是否像我一样为之一颤呢 xff1f 当科技不断发展 xff0c 技术迅速迭代 xff0c 程序员愈发年轻化的今天 xff0c 而作
  • 面试大厂必读、小厂吊打面试官必读书籍推荐

    通过我多年在互联网公司摸爬滚打 xff0c 以及近三年一直担任公司技术面试管经历 xff0c 本文结合我的工作经历 xff0c 分享给众多从事以及将要从事java后端软件开发的程序员们推荐一些必读书籍 xff0c 但并不只限于技术类书籍 深
  • 梦回大学,因它难以入睡,今一文总结之

    依稀记得10年前的大学第一门课就是它 c语言 xff0c 而指针作为c语言的核心之一 xff0c 当时一直难以理解 xff0c 从而转战java 而今10余年过去了 xff0c 依然还是放不下它 xff0c 也同时为了阅读openJDK源码
  • spring-framework核心链路全景图V0.1(持续更新,小白慎入)

    关于spring framework源码 xff0c 业界一直没有一个完整的链路流程全景图来供阅读学习spring framework源码的爱好者来参考 基于这个目的 xff0c 特梳理了spring framework相关的流程链路图 x
  • 真实互联网线上系统JVM内存溢出排查流程(文末彩蛋)

    起因 xff1a 近期在工作中发生因jvm内存溢出导致线上应用进程崩溃 xff0c 导致服务瞬间瘫痪 期间发现集群中每台应用服务器JVM内存使用率高达96 左右 xff0c 存在瞬间内存打满 xff0c 导致服务瘫痪情况 根据经验分析 xf
  • make: warning:  Clock skew detected.  Your build may be incomplete.

    这种问题一般是从一个设备拷贝到另一个设备上 xff0c 编译出现问题 xff1a 这种问题的原因是时钟偏差导致的 xff0c 就是检测到两个设备系统之间的时间上存在差距 xff1a 解决方案 xff1a find type f xargs
  • docker registry.docker-cn.com无法访问

    有时候我们在pull镜像的时候总是很慢 xff0c 这个时候网上的答案是把镜像的地址改成registry docker cn com以提高镜像拉取速度 34 registry mirrors 34 34 http registry dock
  • Java中的有序集合

    面试的时候经常会被问道这样一个问题 xff1a Java集合中哪些是有序的 xff0c 哪些不是 xff1f 我们通常的回答是List LinkedHashMap LinkedHashSet TreeMap TreeSet是有序的 xff0
  • MySQL中的char、varchar(10)、varchar(1000)的区别

    这里写自定义目录标题 tipsMySQL中的varchar与char的区别varchar 100 与varchar 1000 的区别参考 tips 若无特殊指明 xff0c 文中提到的存储空间指的都是占用磁盘空间 MySQL中的varcha
  • validation参数检验 - 注解介绍

    文章目录 Maven 依赖注解介绍javax validation 中的注解 xff08 22个 xff09 Null NotNullNotBlankNotEmptySizeAssertFalse AssertTrueDecimalMax
  • 基于STM32与OneNet平台的智能家居系统设计(代码开源含自制APP代码)

    前言 xff1a 本文为手把手教学的基础物联网开发设计 xff0c 项目包含对下位机 xff08 MCU对外设数据读取与控制 xff09 和上位机 xff08 包含服务平台和APP端 xff09 的设计 下位机选取STM32作为MCU xf
  • CountDownLatch 的用法

    CountDownLatch 的用法 方法构造方法 CountDownLatch int count countDown long getCount await boolean await long timeout TimeUnit uni