CountDownLatch用法、详解

目录

​编辑

概述:

应用场景:

优点:

缺点:

主要方法:

1. `CountDownLatch(int count)`:

2. `void await()`:

3. `boolean await(long timeout, TimeUnit unit)`:

4. `void countDown()`:

案例:

1、猴哥吃蕉====await()

执行结果:

分析:

2、猴哥吃蕉====await(5, TimeUnit.SECONDS);

执行结果

分析:

总结:


概述:

`CountDownLatch`是Java并发包中的一个同步工具类,用于控制线程的执行顺序和协调多个线程之间的操作。它通过一个计数器来实现,计数器的初始值由用户指定,每当一个线程完成了特定任务或达到了某个状态,计数器的值就会减少。当计数器的值变为0时,等待`CountDownLatch`的线程将被释放。

应用场景:

`CountDownLatch`常用于以下场景:

1. 主线程等待多个子线程完成任务后再继续执行。

2. 多个线程等待某个共享资源就绪后再同时开始执行。

3. 控制多个线程按照特定的顺序执行。

优点:

1. 简单易用:`CountDownLatch`提供了简单的接口,易于使用和理解。

2. 灵活性:可以根据实际需求设置等待的线程数量,可以灵活地控制线程的执行顺序和协调多个线程之间的操作。

缺点:

1. 一次性:`CountDownLatch`的计数器只能减少到0,一旦减少到0后,无法重置计数器,因此只能使用一次。

2. 无法逆转:一旦计数器的值减少到0,等待线程将被释放,无法再次等待。

主要方法:

1. `CountDownLatch(int count)`:

构造函数,用于创建一个`CountDownLatch`对象,并指定需要等待的线程数量。

2. `void await()`:

使当前线程等待,直到`count`值减少到0。它会阻塞当前线程,直到所有线程都调用了`countDown()`方法,如果`count`值已经为0,则该方法立即返回。

3. `boolean await(long timeout, TimeUnit unit)`:

方法与`await()`方法类似,但它还接受一个超时时间参数。使当前线程等待,直到`count`值减少到0或超过指定的超时时间。如果在超时时间内`count`值变为0,则返回`true`;如果超过超时时间仍未达到0,则返回`false`。

4. `void countDown()`:

将`count`值减少1。当某个线程完成了特定任务或达到了某个状态时,应调用此方法来减少`count`值。

案例:

1、猴哥吃蕉====await()



import java.util.concurrent.CountDownLatch;

/**
 * 猴哥
 */
public class MonkeyBanana extends Thread {
    CountDownLatch countDownLatch;
    String name;

    public MonkeyBanana(String name, CountDownLatch countDownLatch) {
        this.name = name;
        this.countDownLatch = countDownLatch;
    }

    @Override
    public void run() {
        System.out.println(name + "开始吃香蕉");
        try {
            long l = (long) (Math.random() * 10000);
            Thread.sleep(l);
            if (l / 1000 == 0) {
                System.out.println(name + "简直不要太厉害了,跟我们表演了一波一口闷香蕉!");
            } else if (l / 1000 > 0 && l / 1000 < 5) {
                System.out.println(name + "在" + l / 1000 + "秒内吃完了香蕉!");
            } else if (l / 1000 == 5) {
                System.out.println(name + "在最后1秒内吃完了香蕉!");
            } else if (l / 1000 > 5) {
                System.out.println(name + "在" + l / 1000 + "秒内吃完了香蕉,已超时!");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            countDownLatch.countDown();//线程倒数器-每次都会减1
        }
    }
}

import java.util.Date;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;

public class CountDownLatchTest {

    public static void main(String[] args) {
        monkeyEatAwait();
    }


    /**
     * 猴哥吃香蕉
     */
    public static void monkeyEatAwait() {
        try {
            //倒数器记数
            CountDownLatch downLatch = new CountDownLatch(1);
            System.out.println("猴哥吃香蕉大赛预备::");
            //倒数3个数
            for (int i = 3; i > 0; i--) {
                System.out.println("倒数 : " + i);
                TimeUnit.SECONDS.sleep(1);
            }
            downLatch.countDown();
            downLatch.await();
            System.out.println("BOOM 开始!");
            //几个猴哥再比赛
            int monkeyNum = 5;//需要等待的线程数量。也就是说,这些线程执行完之后才会往下继续走
            CountDownLatch countDownLatch = new CountDownLatch(monkeyNum);
            for (int i = 0; i < monkeyNum; i++) {
                new MonkeyBanana("猴哥" + (i + 1), countDownLatch).start();
            }
            //等待所有猴哥都吃完香蕉
            countDownLatch.await();
            System.out.println("所有猴哥都吃完了香蕉!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
执行结果:

分析:

这个是等待所有猴哥都吃完香蕉。也就是所有的子线程任务都走完之后才会走主线程,执行主线程方法。

2、猴哥吃蕉====await(5, TimeUnit.SECONDS);

import java.util.Date;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;

public class CountDownLatchTest {

    public static void main(String[] args) {
        monkeyEatAwaitPar();
    }

    /**
     * 猴哥吃香蕉
     */
    public static void monkeyEatAwaitPar() {
        try {
            //倒数器记数
            CountDownLatch downLatch = new CountDownLatch(1);
            System.out.println("猴哥吃香蕉大赛预备::");
            //倒数3个数
            for (int i = 3; i > 0; i--) {
                System.out.println("倒数 : " + i);
                TimeUnit.SECONDS.sleep(1);
            }
            downLatch.countDown();
            downLatch.await();
            System.out.println("BOOM 开始!");
            //几个猴哥再比赛
            int monkeyNum = 5;//需要等待的线程数量。也就是说,这些线程执行完之后才会往下继续走
            CountDownLatch countDownLatch = new CountDownLatch(monkeyNum);
            for (int i = 0; i < monkeyNum; i++) {
                new MonkeyBanana("猴哥" + (i + 1), countDownLatch).start();
            }
            //超时判断
            boolean await = countDownLatch.await(5, TimeUnit.SECONDS);
            //超过5秒结束比赛
            if (!await) {
                System.out.println("时间到!");
            } else {
                System.out.println("所有猴哥都吃完了香蕉!");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
执行结果

分析:

这里我们用了带入参的await方法,判断如果吃香蕉时间超出5秒钟,则算是失败!可以处理特殊情况下线程卡死,超时等状态。

总结:

`CountDownLatch`是一个非常有用的同步工具,适用于需要等待多个线程完成任务或达到某个状态后再继续执行的场景。它简单易用,但只能使用一次且无法逆转。在合适的场景下,使用`CountDownLatch`可以有效地实现线程之间的同步和协调。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Python】计算一年内的总天数(还有跨年日期)

花了一段时间才找到Python中求一年中总日数&#xff08;total day of the Year&#xff09;的格式代码&#xff0c;所以也把计算方法记录下来。 基本 首先&#xff0c;简单地找出一年中的总天数&#xff0c; strftime() 和 strptime() 的格式代码是 %j ↓看这里 使用 strft…

基于当前实时云渲染的特点,用户体验主要受哪些因素影响?

在回答这个问题之前我们首先需要理解什么是实时云渲染&#xff1f; 点量实时云渲染是一种基于云计算低延迟传输&#xff0c;实现各种轻终端便捷使用云端大型软件和3D应用的一种云技术解决方案。这一技术解决方案通过将应用程序或内容置于云端服务器上运行&#xff0c;然后以视…

测试用例设计方法六脉神剑——第四剑:石破天惊,功能图法攻阵

1 引言 前面几篇文章为我们讲述了因果图、判定表、正交试验等几种方法&#xff0c;主要是针对于不同条件输入输出的组合进行测试&#xff0c;但在实际需求中&#xff0c;我们也常会遇到需要对被测对象的状态流转进行验证的情况&#xff0c;此时前面几种方法将不再适用&#xf…

测试用例设计方法:功能图

1 引言 前面几篇文章为我们讲述了因果图、判定表、正交试验等几种方法&#xff0c;主要是针对于不同条件输入输出的组合进行测试&#xff0c;但在实际需求中&#xff0c;我们也常会遇到需要对被测对象的状态流转进行验证的情况&#xff0c;此时前面几种方法将不再适用&#xf…

OpenHarmony 鸿蒙系统之开发环境安装

一、首先在下方链接网址中下载DevEco Studio的安装包。 DevEco Studio历史版本下载-HarmonyOS应用开发官网

Linux CentOS7 Docker安装Jenkins

1 sudo yum update #确保yum包更新到最新 service network restart #重启网络 2、查询镜像 docker search jenkins 3、拉取镜像 docker pull jenkins/jenkins #拉取镜像 4、创建Jenkins工作目录&#xff0c;并将容器内目录挂载到此目录…

23.12.10日总结

周总结 这周三的晚自习&#xff0c;学姐讲了一下git的合作开发&#xff0c;还有懒加载&#xff0c;防抖&#xff0c;节流 答辩的时候问了几个问题&#xff1a; 为什么在js中0.10.2!0.3? 在js中进行属性运算时&#xff0c;会出现0.10.20.300000000000000004js遵循IEEE754标…

CSS伪元素的特殊机制

概念 伪元素是CSS中的一种特殊机制&#xff0c;用于在元素的特定位置插入虚拟的内容。它们不是实际存在于HTML文档中的元素&#xff0c;而是通过CSS样式来创建和控制的。 伪元素使用双冒号&#xff08;::&#xff09;作为标识符&#xff0c;用于区分伪类选择器&#xff08;使…

Linux Shell——基本语法(变量、流程控制)

shell基本语法 一、变量二、流程控制 总结 最近学习了shell脚本&#xff0c;记录一下相关语法 一、变量 变量是很重要的&#xff0c;是用于存储数据值的容器 变量名要遵循以下规则&#xff1a; &#xff08;1&#xff09;只能包含字母、数字和下划线 &#xff08;2&#xff09…

鸿蒙开发组件之Web

一、加载一个url myWebController: WebviewController new webview.WebviewControllerbuild() {Column() {Web({src: https://www.baidu.com,controller: this.myWebController})}.width(100%).height(100%)} 二、注意点 2.1 不能用Previewer预览 Web这个组件不能使用预览…

Android camera的metadata

一、实现 先看一下metadata内部是什么样子&#xff1a; 可以看出&#xff0c;metadata 内部是一块连续的内存空间。 其内存分布大致可概括为&#xff1a; 区域一 &#xff1a;存 camera_metadata_t 结构体定义&#xff0c;占用内存 96 Byte 区域二 &#xff1a;保留区&#x…

Linux install manual 1Panel

前言 1Panel 是一个现代化、开源的 Linux 服务器运维管理面板。1Panel 的功能和优势包括: 快速建站:深度集成 Wordpress 和 Halo,域名绑定、SSL 证书配置等一键搞定;高效管理:通过 Web 端轻松管理 Linux 服务器,包括主机监控、文件管理、数据库管理、容器管理等;安全可…

Qt图像处理-Qt中配置OpenCV打开本地图片

本文讲解Qt中配置OpenCV过程并用实例展示如何使用OpenCV打开图片(windows环境下) 一、下载OpenCv 本文使用版本OpenCV-MinGW-Build-OpenCV-3.4.5 下载地址: https://codeload.github.com/huihut/OpenCV-MinGW-Build/zip/refs/heads/OpenCV-3.4.5 点击Code-local-Downlo…

大模型的实践应用13-量化后的通义千问Qwen的18亿参数在CPU上的部署,最小2GB显存可跑,并利用两种文本流式方式输出

大家好,我是微学AI,今天给大家介绍大模型的实践应用13-量化后的通义千问Qwen的18亿参数在CPU上的部署,最小2GB显存可跑,并利用两种文本流式方式输出。Qwen-1_8B-Chat是阿里云研发的通义千问大模型系列的18亿参数规模的模型。Qwen-1.8B是基于Transformer的大语言模型, 在超大…

LabVIEW进行癌症预测模型研究

LabVIEW进行癌症预测模型研究 癌症是一种细胞异常增生的疾病。随着年龄的增长&#xff0c;细胞分裂速度放缓&#xff0c;但癌细胞会失去控制地不断分裂&#xff0c;形成可能良性或恶性的肿瘤。 2012年的国际癌症数据显示&#xff0c;新发癌症病例和癌症相关死亡人数有所增加。…

.NET 开发人员,迎接高薪的挑战,你准备好了吗?

我发现我对编程的热情深深植根于我对逻辑的偏好。加入CSDN,标志着进入 .NET 开发人员世界的激动人心的旅程的开始。下面我与您分享我的故事。 编程之路 我大学是主修通信计算机创新&#xff0c;各种各样的选修课程&#xff0c;从平面设计、UX/UI 设计、数字营销到电影&#x…

在Node.js中MongoDB删除数据的方法

本文主要介绍在Node.js中MongoDB删除数据的方法。 目录 Node.js中MongoDB删除数据使用mongodb库删除数据使用Mongoose库删除数据 Node.js中MongoDB删除数据 在Node.js中&#xff0c;可以使用mongodb和Mongoose库来连接和操作MongoDB数据库。 下面是分别使用这两个库在MongoDB中…

双端队列和优先级队列

文章目录 前言dequedeque底层设计迭代器设计 priority仿函数数组中的第k个最大元素优先级队列模拟实现pushpop调整仿函数存储自定义类型 前言 今天要介绍比较特殊的结构&#xff0c;双端队列。 还有一个适配器&#xff0c;优先级队列。 deque 栈的默认容器用了一个deque的东西…

福德机械:植保无人机的领航者

亲爱的读者们&#xff0c;欢迎来到福德机械的神奇世界。在这个充满活力和创新的世界里&#xff0c;我们专注于植保无人机的发展与应用&#xff0c;以实现农业现代化、智能化和高效化的目标。植保无人机&#xff0c;作为一种高效、环保和安全的农业工具&#xff0c;已经逐渐成为…

自动化测试流程详解

最近很多小伙伴问我自动化测试到底该怎么做&#xff1f;流程是什么样的&#xff1f;在每个阶段都需要注意什么&#xff1f;本文也就主要从自动化测试的基本流程入手&#xff0c;对面试自动化测试工程师的同学会有不少帮助。对于在职的朋友&#xff0c;也可以参考此流程&#xf…