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,一经查实,立即删除!

相关文章

常见的DOM元素与JavaScript的交互方式[示例]

DOM&#xff08;Document Object Model&#xff09;是一个编程接口&#xff0c;用于在浏览器中表示和操作 HTML 和 XML 文档。通过 DOM&#xff0c;开发人员可以使用 JavaScript 等编程语言来操纵网页上的各种元素&#xff0c;例如添加、删除、修改元素、响应用户事件等。 以下…

【软件工程】测试规格

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

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

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

使用Python转换图片中的颜色

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

【Rust】基础语法

变量&#xff0c;基本类型&#xff0c;函数&#xff0c;注释和控制流&#xff0c;这些几乎是每种编程语言都具有的编程概念。 这些基础概念将存在于每个 Rust 程序中&#xff0c;及早学习它们将使你以最快的速度学习 Rust 的使用。 变量 首先必须说明&#xff0c;Rust 是强类…

单链表的排序

目录 题目来源&#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 语句会加行级锁&#…

WPF —— 关键帧动画

wpf动画类型 1<类型>Animation这些动画称为from/to/by动画或者叫基本动画&#xff0c;他们会在起始值或者结束值进行动画处理&#xff0c;常用的例如 <DoubleAnimation> 2 <类型>AnimationUsingKeyFrames: 关键帧动画&#xff0c;功能要比from/to这些动画功…

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…

python图书自动折扣系统

在Python中创建一个图书自动折扣系统可以帮助书店或在线商城自动化地管理图书销售的折扣过程。这样的系统可以根据图书的销量、存货或者促销活动来动态调整折扣率。 图书自动折扣系统概述 图书自动折扣系统的目的是根据预设的规则自动计算图书的折扣。例如&#xff0c;我们可…

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;但是比较且可视化功…

【 C++对C语言的拓展 】 引用

引用 1.1 变量名 变量名实质上是一段连续存储空间的别名&#xff0c;是一个标号(门牌号) 通过变量来申请并命名内存空间. 通过变量的名字可以使用存储空间. 问题&#xff1a;对一段连续的内存空间只能取一个别名吗&#xff1f; 1.2 引用的概念 变量名&#xff0c;本身…

centos7 FastDFS一键自动安装脚本

FastDFS 一键自动安装脚本 目录 FastDFS 一键自动安装脚本1. 简介2. 脚本功能3. 使用说明准备工作执行脚本 4. 注意事项5.下载6.代码解释 1. 简介 该脚本是一个用于在离线环境下一键自动安装 FastDFS 的 Bash 脚本。它包含了安装 FastDFS 的所有步骤&#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…