JUC之CountDownLatch与CyclicBarrier

news2024/10/5 19:14:51

1.前言

java.util.concurrent包中为我们提供了很多的线程同步工具类,例如CountDownLatchCyclicBarrier,那么它们主要的用途是什么呢?且看后续分析。

2.CountDownLatch

2.1 什么是CountDownLatch

CountDownLatch,顾名思义,这是一个带计数器的线程同步工具。我们来看官方解释:

A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.

意味着:CountDownLatch是一个线程同步工具,它允许一个或多个线程进入等待状态,直到其他线程执行完毕后,这些等待的线程才继续往下执行。

这个解释或许对于没有接触过老铁还比较生涩,不方,我们还有实战环节。

2.2 CountDownLatch使用场景

其实,在我们的生活中是有很多场景可以运用CountDownLatch来进行实现的。

这是阳光明媚的一天,部门小伙伴相约春游,滴滴师傅已经达到上车点了,就等各位小伙伴全部上车后,就可以出发了。怎么样,这个场景是不是和CountDownLatch的概念很契合呀,但是我们先用Thread.join()的方式来实现,然后才是我们的CountDownLatch,接下来我们通过代码来实现吧。

1)Thread.join()实现

主要思路:

1)一个滴滴师傅线程,正在等待所有小伙伴上车,上车后继续运行

2)五个小伙伴线程,相继上车

代码示例:

public class CountDownLatchTest {
    @SneakyThrows
    public static void main(String[] args) {
        DriverThread threadDriver = new DriverThread();
        Thread threadA = new Thread(() -> System.out.println(Thread.currentThread().getName() + "已上车"), "张三");
        Thread threadB = new Thread(() -> System.out.println(Thread.currentThread().getName() + "已上车"), "张四");
        Thread threadC = new Thread(() -> System.out.println(Thread.currentThread().getName() + "已上车"), "张五");
        Thread threadD = new Thread(() -> System.out.println(Thread.currentThread().getName() + "已上车"), "张六");
        Thread threadE = new Thread(() -> System.out.println(Thread.currentThread().getName() + "已上车"), "张七");
        threadDriver.setThreads(List.of(threadA, threadB, threadC, threadD, threadE));
        threadDriver.start();
        threadA.start();
        threadB.start();
        threadC.start();
        threadD.start();
        threadE.start();
    }

    static class DriverThread extends Thread {

        private List<Thread> threads;

        public List<Thread> getThreads() {
            return threads;
        }

        public void setThreads(List<Thread> threads) {
            this.threads = threads;
        }

        @SneakyThrows
        @Override
        public void run() {
            System.out.println("滴滴师傅已经达到上车点,请各位小伙伴尽快上车哟");
            for (Thread thread : getThreads()) {
                thread.join();
            }
            System.out.println("所有小伙伴全部上车,向着目的地进发");
        }
    }
}

执行结果:

我们使用Thread.join()的方式,实现了需求,不过大家有没有发现,这种方式其实是相当的麻烦,一个线程需要等待其他的若干个线程执行完毕才能继续往下执行,这个线程就需要持有这些线程的实例,并调用join()方法。那么有没有更优雅的方式呢?

接下来轮到主角CountDownLatch登场了,话不多说直接开干。

代码示例:

public class CountDownLatchTest {
    @SneakyThrows
    public static void main(String[] args) {
        // 5个小伙伴相约春游
        // 构造计数器为5的CountDownLatch,因为我们有5个小伙伴
        CountDownLatch countDownLatch = new CountDownLatch(5);
        new DriverThread(countDownLatch).start();
        CustomRunnable customRunnable = new CustomRunnable(countDownLatch);
        new Thread(customRunnable, "张三").start();
        new Thread(customRunnable, "张四").start();
        new Thread(customRunnable, "张五").start();
        new Thread(customRunnable, "张六").start();
        new Thread(customRunnable, "张七").start();
    }

    static class DriverThread extends Thread {

        private CountDownLatch countDownLatch;

        public DriverThread(CountDownLatch countDownLatch) {
            this.countDownLatch = countDownLatch;
        }

        @SneakyThrows
        @Override
        public void run() {
            System.out.println("滴滴师傅已经达到上车点,请各位小伙伴尽快上车哟");
            // 使当前线程进入等待状态,直到count = 0 时,唤醒此线程
            countDownLatch.await();
            System.out.println("所有小伙伴全部上车,向着目的地进发");
        }
    }

    static class CustomRunnable implements Runnable {

        private CountDownLatch countDownLatch;

        public CustomRunnable(CountDownLatch countDownLatch) {
            this.countDownLatch = countDownLatch;
        }

        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + "已上车");
            // 将计数器减1,直到count = 0,等待的线程就会继续执行
            countDownLatch.countDown();
        }
    }
}

执行结果:

确实,整个代码会简洁许多。这就是CountDownLatch的用法啦。

接下来我们来分析一下实现代码:

1)CountDownLatch构造方法

创建CountDownLatch,并为计数器设置一个初始值。

public CountDownLatch(int count) {}

2) CountDownLatch.countDown()

目的就是让计数器的数值减1。

public void countDown() {
    sync.releaseShared(1);
}

3)CountDownLatch.await()

使得当前线程进入等待状态,直到计数值为0,该线程才会继续向下执行

public void await() throws InterruptedException {
    sync.acquireSharedInterruptibly(1);
}

3.CyclicBarrier

3.1 什么CyclicBarrier

CyclicBarrier:直译的意思是循环屏障,听上去意思是可以当成一个屏障,并且可以重复使用。来看官方的解释:

A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point.

这意味着,CyclicBarrier是一个线程同步工具,它允许一组线程彼此等待,直到这组线程全部执行完毕。

3.2 CyclicBarrier使用场景

这么看上去,这个概念很契合我们的赛跑比赛啊,运动员在起跑线前等待所有运动员准备完毕后,比赛才会正式开始。

接下来我们开始模拟这个场景:

public class CyclicBarrierTest {
    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(5, () -> System.out.println("所有运动员准备完毕,发令员使用发令枪发出信号,比赛开始。"));
        CustomRunnable customRunnable = new CustomRunnable(cyclicBarrier);
        new Thread(customRunnable, "张三").start();
        new Thread(customRunnable, "张四").start();
        new Thread(customRunnable, "张五").start();
        new Thread(customRunnable, "张六").start();
        new Thread(customRunnable, "张七").start();
    }

    static class CustomRunnable implements Runnable {

        private CyclicBarrier cyclicBarrier;

        public CustomRunnable(CyclicBarrier cyclicBarrier) {
            this.cyclicBarrier = cyclicBarrier;
        }

        @SneakyThrows
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + "准备完毕");
            // 在屏障前等待
            cyclicBarrier.await();
            // 所有线程都达到屏障后,继续执行
            System.out.println(Thread.currentThread().getName() + "跨越起跑线");
        }
    }
}

执行结果:

使用CyclicBarrier,可以很方便的模拟赛跑比赛的场景。

接下来我们分析一下代码实现:

1)构造方法

CyclicBarrier cyclicBarrier = new CyclicBarrier(5, () -> System.out.println("所有运动员准备完毕,发令员使用发令枪发出信号,比赛开始。"));

可以结合我们的CyclicBarrier为我们提供的构造方法

 // parties:表示参与的线程个数,barrierAction:表示所有参与线程都达到屏障时,要执行的命令
public CyclicBarrier(int parties, Runnable barrierAction) {}

2)CyclicBarrier.await();

使得先到的线程在屏障前等待,直到所有线程都达到屏障

cyclicBarrier.await();

3)CyclicBarrier.reset();

使得计数值重置为初始值,这也是为什么叫循环屏障的原因。

4.CountDownLatch和CyclicBarrier的区别

相信大家已经对CountDownLatchCyclicBarrier有所了解,一起来总结一下它们的区别:

  • CountDownLatch是一个线程或多个线程进行等待其他线程执行完毕,CyclicBarrier是线程之间彼此等待。
  • CountDownLatchawait()方法由需要进入等待状态的线程调用,CyclicBarrierawait()方法由所有参与线程调用
  • CountDownLatch的计数值为0后不可重置,CyclicBarrier的计数值为0后可以重置。

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

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

相关文章

从ReentrantLock角度解析AQS

一、概述 闲来不卷&#xff0c;随便聊一点。 一般情况下&#xff0c;大家系统中至少也是JDK8了&#xff0c;那想必对于JDK5加入的一系列功能并不陌生吧。那时候重点加入了java.util.concurrent并发包&#xff0c;我们简称为JUC。JUC下提供了很多并发编程实用的工具类&#xf…

风光及负荷多场景随机生成与缩减

目录 1 主要内容 计算模型 场景生成与聚类方法应用 2 部分程序 3 程序结果 4 程序链接 1 主要内容 该程序方法复现了《融合多场景分析的交直流混合微电网多时间尺度随机优化调度策略》3.1节基于多场景技术的随机性建模部分&#xff0c;该部分是随机优化调度的重要组成部分…

记录-css实现交融文字效果

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 CSS是有魔法的&#xff0c;我们今天来实现一个CSS的动画效果&#xff0c;只需要几行代码就可以搞定。 第一步、我们要将一行文字从中间展开 <!DOCTYPE html> <html lang"en"> &…

面试官:聊聊js原型

一分钟了解原型对象 js分为函数对象和普通对象 &#xff0c;每个对象都有__proto__属性&#xff0c;但是只有函数对象才有prototype属性&#xff0c;prototype属性就是函数的原型对象。 比如说 构造函数通过new 实化一个实例对象&#xff0c;实例对象的__proto__ 指向原型对象…

NumPy 基础知识 :6~10

原文&#xff1a;Numpy Essentials 协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 六、NumPy 中的傅立叶分析 除其他事项外&#xff0c;傅立叶分析通常用于数字信号处理。 这要归功于它在将输入信号&#xff08;时域&#xff09;分离为以离散频率&#xff08;频域&am…

Spring Boot集成Druid实现多数据源的两种方式

目录 项目场景&#xff1a; 一、集成com.baomidou的方式 1、maven依赖&#xff1a; 2、 配置文件&#xff1a; 3、 使用注解切换数据源&#xff1a; 二、基于AOP手动实现多数据源原生的方式 1、maven依赖&#xff1a; 2、 配置文件&#xff1a; 3、 多数据源名称类 4…

数字中国理念引领国企人力资源数字化转型与实践

3月初&#xff0c;《数字中国建设整体布局规划》出台&#xff0c;作为中国数字经济发展的重要指导性文件&#xff0c;规划提出了数字中国建设的总体目标和战略方向&#xff0c;文件详细阐述了数字中国内涵&#xff0c;包含数字经济、数字社会、数字政府以及数字生态等内涵。《规…

制造企业该如何选择MES生产管理系统?盘点四大生产管理系统软件

本文将介绍&#xff1a;1、如何选择MES(生产管理系统&#xff09;&#xff1b;2、盘点四款好用的生产管理系统 生产管理系统即MES(Manufacturing Execution System)&#xff0c;制造执行系统。是面向车间生产的管理系统。在产品从工单发出到成品完工的过程中&#xff0c;MES系…

1206. 设计跳表

1206. 设计跳表 不使用任何库函数&#xff0c;设计一个 跳表 。 跳表 是在 O(log(n)) 时间内完成增加、删除、搜索操作的数据结构。跳表相比于树堆与红黑树&#xff0c;其功能与性能相当&#xff0c;并且跳表的代码长度相较下更短&#xff0c;其设计思想与链表相似。 例如&a…

如何收集EMC VPLEX 日志和VPLEX日志的简单解读

对于VPLEX遇到的问题&#xff0c;和二线沟通最快最有效的办法就是收集完整的日志&#xff0c;而不是拍一个照片。本文就详细介绍如何收集日志&#xff1f;和那些日志文件对我们分析问题是有价值的。 命令行ssh登录Vplex 管理控制台&#xff0c;然后进入Vplexcli命令行&#xf…

Windows安装Nginx并配置负载均衡

Nginx简介 Nginx是一款自由的、开源的、高性能的HTTP服务器和反向代理服务器&#xff1b;同时也是一个IMAP、POP3、SMTP代理服务器&#xff1b;Nginx可以作为一个HTTP服务器进行网站的发布处理&#xff0c;另外Nginx可以作为反向代理进行负载均衡的实现。 Nginx使用基于事件驱动…

HOJ项目部署(前后端及其判题机)

文章目录HOJ项目部署1 项目准备1.1 拉取HOJ项目到本地1.2 项目包结构解读2 后端部署DataBackup2.1 环境准备1&#xff09;项目基本数据导入2&#xff09;Nacos环境配置2.2 修改配置1&#xff09;修改application-prod.yml2&#xff09;修改bootstrap.yml3&#xff09;修改上传文…

【模板特性补充】

目录&#xff1a;前言一、非类型模板参数使用方法使用场景二、模板特化&#xff08;一&#xff09;函数模板特化&#xff08;二&#xff09;类模板特化1.全特化2.偏特化使用场景三、模板分离编译1. 什么是分离编译2.模板的分离编译3.解决方法四、模板总结前言 打怪升级&#x…

你知道多少接口性能优化的方案?

一、背景 针对老项目&#xff0c;去年做了许多降本增效的事情&#xff0c; 二、接口优化方案总结 1.批处理 批量思想&#xff1a;批量操作数据库&#xff0c;这个很好理解&#xff0c;我们在循环插入场景的接口中&#xff0c;可以在批处理执行完成后一次性插入或更新数据库…

Springboot的自动注入

一、开篇 在平时的开发过程中用的最多的莫属springboot了&#xff0c;都知道springboot中有自动注入的功能&#xff0c;在面试过程中也会问到自动注入&#xff0c;你知道自动注入是怎么回事吗&#xff0c;springboot是如何做到自动注入的&#xff0c;自动注入背后的原理是什么&…

基于 RocketMQ Connect 构建数据流转处理平台

作者&#xff1a;周波&#xff0c;阿里云智能高级开发工程师&#xff0c; Apache RocketMQ Committer 01 从问题中来的 RocketMQ Connect 在电商系统、金融系统及物流系统&#xff0c;我们经常可以看到 RocketMQ 的身影。原因不难理解&#xff0c;随着数字化转型范围的扩大及…

Linux学习笔记——多线程

文章目录补充知识Linux线程概念线程的优点线程的缺点线程异常线程用途多进程的应用场景Linux进程VS线程重新理解进程进程和线程线程共享的进程资源和环境为什么线程切换的成本更低进程和线程的关系Linux线程控制POSIX线程库创建线程线程ID及进程地址空间布局线程终止线程等待线…

pycharm常用的插件

pycharm等IDE 无法编辑bat文件 Chinese Language Pack 汉化插件 vim CodeGlance 右侧地图 将类似于Sublime中的代码小地图嵌入到编辑器窗格中。使用自定义颜色进行语法高亮&#xff0c;同时使用明暗主题。 Rainbow Brackets&#xff08;必备推荐&#xff09;收费了 这个插件…

【数据库原理 • 六】数据库备份与恢复

前言 数据库技术是计算机科学技术中发展最快&#xff0c;应用最广的技术之一&#xff0c;它是专门研究如何科学的组织和存储数据&#xff0c;如何高效地获取和处理数据的技术。它已成为各行各业存储数据、管理信息、共享资源和决策支持的最先进&#xff0c;最常用的技术。 当前…

Baumer工业相机堡盟工业相机中预处理相机的特性优势以及行业应用

Baumer工业相机堡盟工业相机如何通过BGAPISDK里显示彩色相机和黑白相机的图像&#xff08;C#&#xff09;Baumer工业相机Baumer工业相机的预处理相机的技术背景Baumer工业相机中预处理相机的特性Baumer工业相机中图像压缩相机的特性Baumer工业相机中3D激光相机的特性Baumer工业…