CountDownLatch用法、详解

news2024/11/16 1:29:49

目录

​编辑

概述:

应用场景:

优点:

缺点:

主要方法:

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`可以有效地实现线程之间的同步和协调。

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

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

相关文章

抗EMC干扰高精度隔离放大器ISO EC 系列

SunYuan ISO EC系列模拟信号隔离放大器是一种有较强抗EMC干扰特性的电容耦合隔离混合集成电路。该放大器采用了全新的调制-解调电容耦合隔离技术&#xff0c;模块中信号以数字信号的方式通过电容隔离层进行传输&#xff0c;通过数字调制和电容耦合隔离方式保持信号的完整性&…

电子烟MOS的选型与要求分析

工作原理&#xff1a; 当用户在吸嘴处抽吸时&#xff0c;气流经过进气孔&#xff0c;穿 过电路板上方的咪头&#xff0c;咪头即产生电信号&#xff0c;驱 动芯片板&#xff0c;让电池供电给雾化芯&#xff0c;雾化芯中的 发热丝将电能转化成热能&#xff0c;当温度达到雾化液 …

在线学习平台-学生端

在线学习平台------手把手教程&#x1f448; 学生端课程分页查询 sql: 学生登入时,只能看见自己的所属课程,需要关联查询,查出学生对应的课程 SELECTt2.course_id,t2.course_name,t2.course_cover,t2.teacher_id,t3.nick_name,t2.remarkfrom sys_user t1LEFT JOIN ms_course t…

git查看commit提交记录详情

相关的命令 git log&#xff1a;查看所有的commit提交记录&#xff1b;git show&#xff1a; 查看提交的详情&#xff1b; 首先&#xff0c;需要通过git log显示所有commit记录&#xff1a; 查看最新的commit&#xff1a;git show查看指定commit的所有修改&#xff1a;git s…

计算机网络应用层(期末、考研)

计算机网络总复习链接&#x1f517; 目录 DNS域名服务器域名解析过程分类递归查询&#xff08;给根域名服务器造成的负载过大&#xff0c;实际中几乎不用&#xff09;迭代查询 域名缓存&#xff08;了解即可&#xff09;完整域名解析过程采用UDP服务 FTP控制连接与数据连接 电…

LLM之Prompt(三)| XoT:使用强化学习和蒙特卡罗树搜索将外部知识注入Prompt中,性能超过CoT,ToT和GoT

​论文地址&#xff1a;https://arxiv.org/pdf/2311.04254.pdf 一、当前Prompt技术的局限性 LLM使用自然语言Prompt可以将复杂的问题分解为更易于管理的“thought”可以回复用户的问题。然而&#xff0c;大多数现有的Prompt技术都有局限性&#xff1a; 输入输出&#xff08;I…

centos7服务器上的文件上传到谷歌云盘(google drive)

1,下载gdrive客户端&#xff0c;Releases glotlabs/gdrive GitHub 2&#xff0c;下载完解压,并移动到cp gdrive /usr/local/bin/ 3&#xff0c;查看是否安装成功 4,添加账户&#xff0c;gdrive account add 根据链接&#xff0c;创建Client id和 Client secret 5,填写Client…

HarmonyOS(ArkTS)基础组件参数 媒体类型讲解

我们这里做了一个空的容器 然后 我们可以这样写 Entry Component struct Index {build() {Row() {Column() {Text("你好")Divider()Button("点击")}.width(100%)}.height(100%)} }这里 我们分别使用了三个组件 Text文本组件 Divider分割线组件 Button按钮…

【通俗易懂】基于fabric8io操作k8s集群实战(pod、deployment、service、volume)

目录 前言一、基于fabric8io操作pod1.1 yaml创建pod1.2 fabric8io创建pod案例 二、基于fabric8io创建Service&#xff08;含Deployment&#xff09;2.1 yaml创建Service和Deployment2.2 fabric8io创建service案例 三、基于fabric8io操作Volume3.1 yaml配置挂载存储卷3.2 基于fa…

智能优化算法应用:基于乌鸦算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于乌鸦算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于乌鸦算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.乌鸦算法4.实验参数设定5.算法结果6.参考文献7.MA…

go http服务接收POST请求文件同时接收自定义参数

以gin框架为例&#xff0c;其它框架功能都有&#xff0c;大同小异。 gin中接收文件的方式如下&#xff1a; 单个文件 file : c.FormFile("file") 多个文件 form, err : c.MultipartForm() files : form.File["uoload[]"] 此时files就是所有发来的文件…

JS实现日历表

有需要的可以用一下&#xff0c;这是一个简单的demo. HTML&#xff1a; <table><thead><tr><th colspan"2"><span class"left"></span></th><th colspan"3"><span class"time"&g…

积木艺术化佳乐专用五万颗花型艺术积木诠释东方之美

12月11日,为期四天以“惊喜AMAZE”为主题的2023广州设计周圆满落幕!KALOS BLOCKS佳乐专凭借优秀的产品设计与场馆设计,开展四天,流量爆棚,圈粉无数,在设计周展馆中C位出道,获得现场观众和众多设计师的一致好评! 以梅花之形,现东方之美—— 一次唤醒艺术升维的仪式感一次东方美学…

【数学建模】《实战数学建模:例题与讲解》第九讲-时间序列分析(含Matlab代码)

【数学建模】《实战数学建模&#xff1a;例题与讲解》第九讲-时间序列分析&#xff08;含Matlab代码&#xff09; 基本概念确定性时间序列分析方法平稳时间序列模型ARIMA模型季节性序列 习题8.11. 题目要求2.解题过程3.程序4.结果 习题8.21. 题目要求2.解题过程3.程序4.结果 习…

Qt/C++音视频开发59-使用mdk-sdk组件/原qtav作者力作/性能凶残/超级跨平台

一、前言 最近一个月一直在研究mdk-sdk音视频组件&#xff0c;这个组件是原qtav作者的最新力作&#xff0c;提供了各种各样的示例demo&#xff0c;不仅限于支持C&#xff0c;其他各种比如java/flutter/web/android等全部支持&#xff0c;性能上也是杠杠的&#xff0c;目前大概…

数字图像处理(实践篇)二十五 使用hyperlpr3进行车牌识别

目录 1 HyperLPR 2 中文字体文件下载 3 实践 1 HyperLPR HyperLPR是一个基于Python的使用深度学习针对对中文车牌识别的实现,与开源的EasyPR相比,它的检测速度和鲁棒性和多场景的适应性都要好于EasyPR。 HyperLPR3是一个高性能开源中文车牌识别框架。

leetcode-138-随机链表的复制(Java实现)

题目&#xff1a; 给你一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机指针 random &#xff0c;该指针可以指向链表中的任何节点或空节点。 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成&#xff0c;其中每个新节点的值都设为其对应的原节点…

【Netty】Socket与I/O模型

目录 Socket网络编程Socket概述Socket整体流程代码实现 I/O模型说明BIO(同步并阻塞)NIO(同步非阻塞)AIO(异步非阻塞)BIO、NIO、AIO适用场景 Socket网络编程 Socket概述 Socket&#xff0c;套接字就是两台主机之间逻辑连接的端点。TCP/IP协议是传输层协议&#xff0c;主要解决…

免费分享一套Springboot+Vue前后端分离的校园二手交易平台,挺漂亮的

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的SpringbootVue前后端分离的校园二手交易平台&#xff0c;分享下哈。 项目视频演示 【免费】SpringbootVue校园二手交易平台系统 毕业设计 Java毕业设计_哔哩哔哩_bilibili 项目介绍 校园二手交易网站是一…

100V耐压 内置MOS ESOP8 40V输入 转5V 2.1A恒压输出

100V耐压内置MOS ESOP8 40V输入转5V 2.1A恒压输出 芯片测试数据如下图&#xff1a;