CountDownLatch 详解

CountDownLatch 用法详解

  • CountDownLatch 详解
    • 1 原理
    • 2 常见用法
    • 3 方法介绍
    • 4 示例及使用

CountDownLatch 详解

CountDownLatch(倒计时门闩)是Java并发包中的一个工具类,用于协调多个线程之间的同步。它允许一个或多个线程等待其他线程完成操作后再继续执行。

CountDownLatch 通过一个计数器来实现,该计数器在初始化时设定,然后递减。当计数器值为0时,等待的线程会被唤醒。

1 原理

CountDownLatch是通过一个计数器来实现等待操作的,它的基本原理如下:

计数器的初始化值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就相应得减1。当计数器到达0时,表示所有的线程都已完成任务,然后在闭锁上等待的线程就可以恢复执行任务。

在这里插入图片描述

2 常见用法

用法一

某一线程在开始运行前等待n个线程执行完毕。

  1. 创建 CountDownLatch 对象时,需要传入一个初始计数值。这个值表示需要等待的线程数量。
  2. 当一个线程完成了它的任务后,可以调用 countDown() 方法来递减计数器的值。
  3. 其他线程可以调用 await() 方法来阻塞等待,直到计数器值为0。

用法二

实现多个线程开始执行任务的最大并行性。注意是并行性,不是并发,强调的是多个线程在某一时刻同时开始执行。类似于赛跑,将多个线程放到起点,等待发令枪响,然后同时开跑。

  1. 初始化一个共享的CountDownLatch(1),将其计数器初始化为1。
  2. 多个线程在开始执行任务前首先 coundownlatch.await()。
  3. 当主线程调用 countDown() 时,计数器变为0,多个线程同时被唤醒。

结构:

CountDownLatch的UML类图如下:

在这里插入图片描述

CountDownLatch 的数据结构很简单,它是通过"共享锁"实现的。它包含了sync对象,sync是Sync类型。Sync是实例类,它继承于 AQS 。

源代码:

package java.util.concurrent;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");} else {this.sync = new Sync(count);}}public void await() throws InterruptedException {this.sync.acquireSharedInterruptibly(1);}public boolean await(long timeout, TimeUnit unit) throws InterruptedException {return this.sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));}public void countDown() {this.sync.releaseShared(1);}public long getCount() {return (long)this.sync.getCount();}public String toString() {return super.toString() + "[Count = " + this.sync.getCount() + "]";}private static final class Sync extends AbstractQueuedSynchronizer {private static final long serialVersionUID = 4982264981922014374L;Sync(int count) {this.setState(count);}int getCount() {return this.getState();}protected int tryAcquireShared(int acquires) {return this.getState() == 0 ? 1 : -1;}protected boolean tryReleaseShared(int releases) {int c;int nextc;do {c = this.getState();if (c == 0) {return false;}nextc = c - 1;} while(!this.compareAndSetState(c, nextc));return nextc == 0;}}
}

从源码中可以看到:

内部类 Sync 继承了 AbstractQueuedSynchronizer,实现了计数器的同步控制逻辑。

其中,tryAcquireShared(int acquires) 方法用于判断是否可以获取同步状态,当计数器为0时返回1,表示可以获取同步状态;

tryReleaseShared(int releases)方法用于释放同步状态,将计数器减1,并使用compareAndSetState(c, nextc)方法保证操作的原子性。

3 方法介绍

CountDownLatch 类主要提供了以下方法:

  1. public CountDownLatch(int count)

    • 构造函数,创建一个 CountDownLatch 对象,并设置初始的计数器值为 count 。
  2. public void await() throws InterruptedException

    • 阻塞当前线程,直到计数器值变为0。如果计数器已经为0,立即返回。如果在等待过程中被中断,则抛出 InterruptedException 异常。
  3. public boolean await(long timeout, TimeUnit unit) throws InterruptedException

    • 阻塞当前线程,直到计数器值变为0或者超时。如果在指定时间内计数器变为0,则返回 true ,否则返回 false 。如果在等待过程中被中断,则抛出 InterruptedException 异常。
  4. public void countDown()

    • 递减计数器的值,表示一个任务已经完成。
  5. public long getCount()

    • 获取当前计数器的值。

4 示例及使用

下面是一个简单的示例,演示了如何使用CountDownLatch来实现线程之间的同步:

import java.util.concurrent.CountDownLatch;public class Main {public static void main(String[] args) throws InterruptedException {final int threadCount = 3;CountDownLatch latch = new CountDownLatch(threadCount);// 创建并启动线程for (int i = 0; i < threadCount; i++) {Thread thread = new Thread(() -> {// 模拟线程执行任务try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Thread " + Thread.currentThread().getId() + " finished its task.");// 任务完成后递减计数器latch.countDown();});thread.start();}// 主线程等待所有子线程完成任务latch.await();System.out.println("All threads have finished their tasks.");}
}

在上面的示例中,主线程通过latch.await()等待所有子线程完成任务,而每个子线程完成任务后调用latch.countDown()来递减计数器。当计数器值变为0时,主线程恢复执行。

在实时系统中的使用场景

  1. 实现最大的并行性:有时我们想同时启动多个线程,实现最大程度的并行性。例如,我们想测试一个单例类。如果我们创建一个初始计数器为1的CountDownLatch,并让其他所有线程都在这个锁上等待,只需要调用一次countDown()方法就可以让其他所有等待的线程同时恢复执行。
  2. 开始执行前等待N个线程完成各自任务:例如应用程序启动类要确保在处理用户请求前,所有N个外部系统都已经启动和运行了。
  3. 死锁检测:一个非常方便的使用场景是你用N个线程去访问共享资源,在每个测试阶段线程数量不同,并尝试产生死锁。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/794994.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【软件工程】测试规格

1. 引言 1.1简介 本次的测试用例是基于核心代码基本开发完毕&#xff0c;在第一代系统基本正常运行后编写的&#xff0c;主要目的是为了后续开发与维护的便利性。 该文档主要受众为该系统后续开发人员&#xff0c;并且在阅读此文档前最后先阅读本系统的需求文档、概要设计文…

谷歌推出多模态视频模型,自动生成丰富动作视频

谷歌的研究人员推出了一款多模态扩散模型——VLOGGER。 用户只需要向VLOGGER输入图像、语音&#xff0c;就能生成带语音、丰富动作的人物视频。VLOGGER基于扩散模型开发而成&#xff0c;并提出了一种全新的架构&#xff0c;将文本生成图像模型与空间、时间控制相结合&#xff…

使用Python转换图片中的颜色

说明&#xff1a;最近在看梵高的画册&#xff0c;我手上的这本画册&#xff08;《文森特梵高》杨建飞 主编&#xff09;书中说&#xff0c;梵高用的颜料里有不耐久的合成颜料&#xff0c;原本的紫色褪成了我们现在所看到的灰蓝色。于是我想&#xff0c;能不能用程序将画中的颜色…

单链表的排序

目录 题目来源&#xff1a; 题目描述&#xff1a; 初始代码&#xff1a; 思路&#xff1a; 具体做法&#xff1a; 我的代码&#xff1a; 优化代码&#xff1a; 对比&#xff1a; 复习&#xff1a;List 基本介绍 常用方法 遍历方式 题目来源&#xff1a; 单链表的排…

MySQL常见锁探究

MySQL常见锁探究 1. 各种锁类型1.1 全局锁1.2 表级锁1.2.1 表锁1.2.2 元数据锁&#xff08;MDL&#xff09;1.2.3 意向锁1.2.4 AUTO-INC 锁 1.3 行级锁1.3.1 Record Lock1.3.2 Gap Lock1.3.3 Next-Key Lock 2. MySQL是如何加锁的&#xff1f;2.1 什么 SQL 语句会加行级锁&#…

Win10 下 Vision Mamba(Vim-main)的环境配置(libcuda.so文件无法找到,windows系统运行失败)

目录 1、下载NVIDIA 驱动程序、cuda11.8、cudnn8.6.0 2、在Anaconda中创建环境并激活 3、下载gpu版本的torch 4、配置环境所需要的包 5、安装causal_conv1d和mamba-1p1p1 安装causal_conv1d 安装mamba-1p1p1 6、运行main.py失败 请直接拉到最后查看运行失败的原因&am…

Pandas:sort_index、sort_values方法的使用

sort_index和sort_values既是Series类型数据自带的方法&#xff0c;也是DataFrame数据自带的方法。本篇博客以DataFrame为例进行讲述。 1 概览 sort_index和sort_values可以将DataFrame中的数据按照索引及值的大小进行排序。这两个方法所包含的参数及其作用都基本一致。如下表…

重读Java设计模式: 桥接模式详解

引言 在软件开发中&#xff0c;经常会遇到需要在抽象与实现之间建立连接的情况。当系统需要支持多个维度的变化时&#xff0c;使用传统的继承方式往往会导致类爆炸和耦合度增加的问题。为了解决这一问题&#xff0c;我们可以使用桥接模式。桥接模式是一种结构型设计模式&#…

【windows】--- nginx 超详细安装并配置教程

目录 一、下载 nginx二、安装三、查看是否安装成功四、配置五、关闭 nginx六 负载均衡七 配置静态资源1. 根目录下的子目录(root)2.完全匹配(alias) 刷新配置&#xff08;不必重启nginx&#xff09;八、后端鉴权 一、下载 nginx 打开 nginx 的官网&#xff1a;nginx.org/ &…

2024.4.3-[作业记录]-day08-CSS 盒子模型(溢出显示、伪元素)

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;HTML5和CSS3悦读 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; 文章目录 作业 2024.4.3-学习笔记css溢出显示单行文本溢出显示省略号多行文本溢出显示省…

Linux基础篇:Linux网络yum源——以配置阿里云yum源为例

Linux网络yum源——以阿里云为例 一、网络yum源介绍 Linux中的YUM&#xff08;Yellowdog Updater, Modified&#xff09;源是一个软件包管理器&#xff0c;它可以自动处理依赖关系并安装、更新、卸载软件包。YUM源是一个包含软件包的远程仓库&#xff0c;它可以让用户轻松地安…

苹果cmsV10 MXProV4.5自适应PC手机影视站主题模板苹果cms模板mxone pro

演示站&#xff1a;http://a.88531.cn:8016 MXPro 模板主题(又名&#xff1a;mxonepro)是一款基于苹果 cms程序的一款全新的简洁好看 UI 的影视站模板类似于西瓜视频&#xff0c;不过同对比 MxoneV10 魔改模板来说功能没有那么多,也没有那么大气&#xff0c;但是比较且可视化功…

服务器硬件构成与性能要点:CPU、内存、硬盘、RAID、网络接口卡等关键组件的基础知识总结

文章目录 服务器硬件基础知识CPU&#xff08;中央处理器&#xff09;内存&#xff08;RAM&#xff09;硬盘RAID&#xff08;磁盘阵列&#xff09;网络接口卡&#xff08;NIC&#xff09;电源散热器主板显卡光驱 服务器硬件基础知识 服务器是一种高性能计算机&#xff0c;用于在…

thinkphp6入门(21)-- 如何删除图片、文件

假设文件的位置在 /*** 删除文件* $file_name avatar/20240208/d71d108bc1086b498df5191f9f925db3.jpg*/ function deleteFile($file_name) {// 要删除的文件路径$file app()->getRootPath() . public/uploads/ . $file_name; $result [];if (is_file($file)) {if (unlin…

论文笔记:Large Language Models as Analogical Reasoners

iclr 2024 reviewer打分5558 1 intro 基于CoT prompt的大模型能够更好地解决复杂推理问题 然而传统CoT需要提供相关的例子作为指导&#xff0c;这就增加了人工标注的成本——>Zero-shot CoT避免了人工标注来引导推理 但是对于一些复杂的任务难以完成推理&#xff0c;例如c…

Type-c转USBA3.0芯片 USBA3.0转Type-c芯片(USB3.1GEN2 多路切换Switch芯片) VL162

VL162具有CC功能的USB Type-C数据开关USB 3.1 Gen2 (10Gbps) VL162 带CC功能的USB Type-C数据开关 支持最高10Gbps 2差分通道&#xff0c;2:1 MUX/DeMUX 兼容10Gbps USB3.1 Gen2 低功耗&#xff0c;6mW在设备模式下有效 高直流共模电压&#xff0c;支持2.0V 28针QFN 3.5 x 4.5m…

人工智能数据分析Python常用库 04 matplotlib库

文章目录 一、matplotlib库的作用与环境配置1、环境配置示例2、改变绘图风格3、保存图片 二、绘制二维图形1、折线图&#xff08;1&#xff09;示例&#xff08;2&#xff09;调整线条颜色&#xff1a;&#xff08;3&#xff09;调整线条风格&#xff08;4&#xff09;调整线宽…

【C语言】_文件内容操作:随机读写

目录 1. fseek 1.1 随机读文件 1.2 随机写文件 2. ftell 3. rewind 当以读方式打开一个存在且存有内容的文件时&#xff0c;文件指针会默认指向第一个元素。以在test4.txt文件中存储abcdef为例&#xff1a; int main() {//打开文件FILE* pf fopen("E:\\C_文件操作…

关系型数据库与非关系型数据库、Redis数据库

相比于其他的内存/缓存数据库&#xff0c;redis可以方便的实现持久化的功能&#xff08;保存至磁盘中&#xff09; 一、关系数据库与非关系型数据库 1.1 关系型数据库 一个结构化的数据库&#xff0c;创建在关系模型基础上一般面向于记录 SQL语句 (标准数据查询语言) 就是一种…

LNMP环境:揭秘负载均衡与高可用性设计

lb1: 192.168.8.5 lb2: 192.168.8.6 web1:192.168.8.7 web2:192.168.8.8 php-fpm: 192.168.8.9 mysql: 192.168.8.10 nfs:192.168.8.11 分别插入镜像 8.5-8.8 分别安装nginx,并设置启动 8.9 安装php 8.10 安装mysql 先配置一台web服务器然后同步 设置网站根目录 cp -…