Java并发工具类 CountDownLatch

『死磕Java并发编程系列』并发编程工具类之CountDownLatch 《死磕 Java 并发编程》系列连载中,大家可以关注一波: ????????『死磕Java并发编程系列』 01 十张图告诉你多线程那些破事 『死磕Java并发编程系列』 02 面试官:说说什么是Java内存模型? 『死磕Java并发编程系列』 03 面试必问的CAS原理你会了吗? 『死磕Java并发编程系列』 04 面试官:说说Atomic原子类的实现原理? ????????『死磕Java并发编程系列』 05 图解Java中那18 把锁 在日常编码中,Java 并发编程可是少不了,试试下面这些并 阅读详情

3.并发工具类

Java并发工具类需要依赖对于Java锁机制的理解,尤其是AQS,可以参见前文:
Java锁机制浅析(一)
Java锁机制浅析(二)之AQS

有了AQS这个并发同步基础类之后,基于AQS实现很多实用的工具类,前面已经分析了ReentrantLock和ReentrantReadWriteLock 接下来分析CountDownLatch、CyclicBarrier、Semaphore。

3.1 CountDownLatch 计数器

3.1.1主要API

方法说明
CountDownLatch(int count)指定计数量的构造函数。
void await()导致当前线程等到锁存器计数到零,除非线程是 interrupted
boolean await(long timeout, TimeUnit unit)使当前线程等待直到锁存器计数到零为止,除非线程为 interrupted或指定的等待时间过去
void countDown()减少锁存器的计数,如果计数达到零,释放所有等待的线程
long getCount()返回当前计数

3.1.2 Demo

CountDownLatch 通常用在等待多个并发任务执行完成后,再继续后续操作的场景中。CountDownLatch的计数不能被重置,它是一个一次性的计数器。
线程调用await()函数后将被阻塞,直到其他线程调用countDown()内部的count减少到零后,被await()阻塞的线程才会被放行。

3.1.2.1 子线程并发统计,主线程对统计结果进行合并

下面的Demo中,模拟3个线程并发统计,主线程在3个线程统计结束后将统计结果汇总。

public class CountDownLatchDemo {
    public static void main(String[] args) throws Exception {
        
        CountDownLatch c = new CountDownLatch(3);	//计数为3
        int[] ary = new int[]{0,0,0};				//模拟多个线程统计结果
        
        long start = new Date().getTime();
        System.out.println("并行统计开始...");

        //任务1统计出数量为10
        new Thread(() -> {
            try {
                Thread.sleep(3000);	//模拟线程耗时
                ary[0] = 10;
                c.countDown();
                System.out.println("线程1统计完成,耗时:"+(new Date().getTime() - start));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();

        //任务2统计结果为20
        new Thread(() -> {
            try {
                Thread.sleep(4000);//模拟线程耗时
                ary[1] = 20;
                c.countDown();
                System.out.println("线程2统计完成,耗时:"+(new Date().getTime() - start));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();

        //任务3统计结果为30
        new Thread(() -> {
            try {
                Thread.sleep(10000);//模拟线程耗时
                ary[2] = 30;
                c.countDown();
                System.out.println("线程3统计完成,耗时:"+(new Date().getTime() - start));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();

        //主线程阻塞,直到所有并发任务执行结束后 对统计结果进行加和
        c.await();
        System.out.println("并行统计结束,总共耗时"+(new Date().getTime() - start));
        int sum = 0;
        for(int i : ary){
            sum += i;
        }
        System.out.println("统计结果汇总:"+sum);
    }
}

执行结果:

并行统计开始…
线程1统计完成,耗时:3111
线程2统计完成,耗时:4108
线程3统计完成,耗时:10112
并行统计结束,总共耗时10112
统计结果汇总:60

3.1.2.2 模拟压力测试设置集合点
public class CountDownLatchDemo2 {

    public static void main(String[] args) throws Exception {

        int n = 10;
        CountDownLatch single = new CountDownLatch(1);
        CountDownLatch count = new CountDownLatch(n);

        for (int i = 0; i < n; i++) {
            new Thread(new LoadTest(single, count)).start();
        }

        //在single.countDown()调用前,所有子线程阻塞在single.await()
        single.countDown();  //通知子线程可以发送交易。
        count.await();       //等待子线程交易完成

    }

    static class LoadTest implements Runnable {
        private CountDownLatch single;
        private CountDownLatch count;
        public LoadTest(CountDownLatch single, CountDownLatch count) {
            this.single = single;
            this.count = count;
        }

        @Override
        public void run() {
            try {
                System.out.println(Thread.currentThread().getName() + ":到达集合点...");
                single.await();
                execute();
                System.out.println(Thread.currentThread().getName() + ":测试完毕...");
                count.countDown();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //模拟测试交易占用时间
        private void execute() throws Exception {
            Thread.sleep(ThreadLocalRandom.current().nextLong(5000));
        }
    }
}

3.1.2 源码

CountDownLatch最核心的两个API都是通过内部Sync继承AQS来实现的;理解了AQS的原理之后,CountDownLatch的思路就非常清晰了。

	/**
	 * 同步等待,通过AQS可中断共享锁方法实现。
	 * 获取锁的逻辑最终由内部类Sync的tryAcquireShared()方法实现。   
	 */
    public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }
    /**
     * 带超时的同步等待。通过AQS的带超时共享锁方法实现
     * 获取锁的逻辑最终由内部类Sync的tryAcquireShared()方法实现。 
     */
    public boolean await(long timeout, TimeUnit unit)
        throws InterruptedException {
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }
	
	/**
	 * 释放锁逻辑,通过AQS释放共享锁方法实现。
	 * 释放锁的逻辑最终由内部类Sync的tryAcquireShared()方法实现。
	 */
    public void countDown() {
        sync.releaseShared(1);
    }
	
	 /**
     * 构造函数,使用count初始化sync
     */
    public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    }
    
	private final Sync sync;
    private static final class Sync extends AbstractQueuedSynchronizer {
        
        //构造函数,将AQS的状态值初始为count
        Sync(int count) { setState(count); }
        //返回AQS的当前状态值 
        int getCount() { return getState(); }
		
		/**
		 * AQS共享锁获取逻辑,由CountDownLatch.await()间接调用
		 * 如果AQS状态值为零则返回1(成功获取锁),否则返回-1(获取锁失败)
		 */
        protected int tryAcquireShared(int acquires) {
            return (getState() == 0) ? 1 : -1;
        }
        
		/**
		 * AQS共享锁获释放,由CountDownLatch.countDown()间接调用
		 * 循环+CAS(递减AQS状态值,直到状态值为零)
		 */
        protected boolean tryReleaseShared(int releases) {
            // Decrement count; signal when transition to zero
            for (;;) {
                int c = getState();
                if (c == 0)
                    return false;
                int nextc = c-1;
                if (compareAndSetState(c, nextc))
                    return nextc == 0;
            }
        }
    }
【JAVA】47. 并发工具类CountDownLatch与CyclicBarrier 是 Java 并发包中的一个工具类,它允许一个或多个线程等待其他线程完成操作。内部维护了一个计数器,在创建对象时需要指定计数器的初始值。当一个线程完成操作后,会调用方法将计数器减 1,当计数器的值变为 0 时,等待的线程会被唤醒继续执行。也是 Java 并发包中的一个工具类,它允许一组线程相互等待,直到所有线程都到达一个屏障点,然后所有线程再继续执行。可以循环使用,当所有线程都到达屏障点后,屏障会被重置,可以继续使用。 阅读详情

相关推荐

Java领域并发工具类:CountDownLatch与CyclicBarrier应用

在现代软件开发中,并发编程已经成为了一个至关重要的技术领域。随着计算机硬件的发展,多核处理器的普及使得程序能够同时执行多个任务,从而提高系统的性能和响应速度。然而,并发编程也带来了许多挑战,例如线程安全、资源竞争等问题。Java作为一种广泛使用的编程语言,提供了丰富的并发工具类来帮助开发者解决这些问题。本文的目的是深入探讨Java中的两个重要并发工具类:CountDownLatch和CyclicBarrier。

AI开发架构师 941

CountDownLatch测试await

CountDownLatch测试await

zhanghua0324的博客 3406

Java并发工具类:CountDownLatch、Semaphore、CyclicBarrier、Exchanger、Phaser

写在前面        在 Java 多线程环境下,JDK 提供了许多的工具类来供开发者使用,这些工具类都在java.util.concurrent 并发包下(俗称JUC),使得我们不需要过多的关心具体业务场景下,应该如何写出同时兼顾线程安全性与高效率的代码。之前文章介绍的:Java 线程池内容,全在这里了,也是 JUC 包下的...

扛麻袋的少年的博客 1747

11.countDownLatch(共享锁)

# countDownLatch(共享锁) CountDownLatch是Java并发包下的一个工具类,latch是门闩的意思。 顾名思义,CountDownLatch就是有一个门闩挡住了里面的人(线程)出来,当count减到0的时候,门闩就打开了,人(线程)就可以出来了。 API //CountDownLatch类只提供了一个构造器:参数count为计数值即state // publi...

qq_30635523的博客 304

Java并发工具类:CountDownLatch

之前的一些并发工具类仍然不能满足一些特定的需求,比如让某一条线程要进行整理最后数据,那么他得先等待其余线程操作数据的线程完成后在执行,如果不给上面两个工具类加锁操作是很难完成对这样复杂的数据操作编写业务的。如果当前线程的孩子吃完了手里的所有糖果了,那么就调用countDown()方法,将计数器-1,那么我们重写的run方法里就可以这么写。最后母亲线程就需要在运行时进行await等待,等到计数器为0时才会唤醒等待,进行收拾桌子的操作。有这么一个案例妈妈等三个孩子吃完糖果然后收拾桌子。...

流楚丶格念的博客 1637

高速PCB设计中串扰的成因、影响与实战控制策略

在高速数字电路与硬件系统设计中,信号完整性是确保系统稳定可靠的核心基础。其核心原理在于,当信号在传输线上传播时,会伴随产生电场与磁场,若相邻导线距离过近,便会通过电磁场耦合产生不期望的能量转移,即串扰。这一现象会直接导致信号波形畸变、时序偏移和噪声裕量降低,严重影响系统性能。从技术价值看,深入理解并有效控制串扰,是提升数据传输速率、保障系统稳定性和降低误码率的关键。其应用场景广泛覆盖了从高速SerDes链路、DDR内存接口到高精度模拟电路等几乎所有现代电子系统。本文聚焦于高速PCB设计中的串扰问题,系统剖析

weixin_27625589的博客 574

java中CountDownLatch的用法

每次有线程调用 countDown()数量-1,假设计数器变为0,countDownLatch.await() 就会被唤醒,继续执行。等待计数器归零,然后再向下执行countDownLatch.await();countDownLatch.countDown() 数量-1。

m0_61366135的博客 425

IP路由原理、静态路由及动态路由区分

什么是路由 路由是指导IP报文发送的路径信息。 直连路由:目的地所在网络与路由器直接相连。 间接路由:目的地所在网络与路由器非直接相连。 静态路由是由管理员手工配置而生成的路由。 动态路由路由器使用路由协议从其他路由器那里获悉的路由。

weixin_42227328的博客 5468

【5】Java并发编程:线程同步工具之CountDownLatch类

今天在分享会上接触到了CountDownLatch,完会后自己学习一下。CountDownLatch是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行。目录CountDownLatch是什么? CountDownLatch如何工作? 在实时系统中的应用场景 应用场景范例CountDownLatch是什么概述CountDownLatch是在java1.5被引入的,跟

happy_horse的博客 1073

Unity URP半透明物体渲染避坑指南:双面渲染与深度写入的实战技巧

本文深入探讨了Unity URP中半透明物体自交叠渲染问题的核心根源与解决方案。针对模型自身交叠导致的排序错误,文章提供了双面渲染与深度写入两种实战技巧,详细分析了其实现原理、性能开销及适用场景,帮助开发者根据项目需求选择最优方案,有效提升玻璃、水体等材质的视觉表现。

sunny的博客 545

09、Flutter FFI Dart Native API

本文介绍了 Dart Native API 的基本用法,解决了 Dart 与 C 异步通讯的问题

eieihihi的专栏 4396

如何用Java代码来做压测

用Java代码来做压测,关键点就在于要让所有的线程都就绪后才开始执行压测逻辑,可以借助countdownlatch来实现。 public class Test { private static final int MAX_CONCURRENCY= 8; private static final CountDownLatch COUNT_DOWN_LATCH = new CountDownLatch(1); public static void ma...

远方的少年 2802

Carsim和Matlab/Simulink联合仿真时Carsim匹配不到Matlab的解决方法

      本人使用Carsim和Matlab/Simulink联合仿真做过用机器学习方法解决ACC和简单换道的仿真,曾将8.02 2016 2018三个版本Carsim反复安装N次,有相同方向的同学或安装过程遇到问题的同学可以加本人qq505625869一起交流经验心得。 一.前言       Carsim是一款很好的联合仿真软件,使用Carsim,可以避免搭建很多非常复杂的动力学模型

Kaikai_Liao的博客 8766

探索 Java 中的并发工具类:CountDownLatch、CyclicBarrier

优先使用工具类:避免重复实现复杂同步逻辑理解底层机制:掌握 AQS(AbstractQueuedSynchronizer)原理监控与调优:使用jconsole监控线程池和锁状态文档与测试:确保工具类使用符合设计契约Java 的并发工具类通过分层设计和灵活组合,提供了强大的线程协作能力。在实际开发中,需根据具体场景选择合适的工具类,并结合性能监控进行持续优化。未来随着 JVM 和硬件的发展,并发工具类将向更智能、更低延迟的方向演进。

潜意识Java的博客 1315

解决Visual C++2008安装失败,error 1935

重装系统后Visual C++没了,其他都能装上但VC2008会报这个error 1935。鉴于我把网上所有的解决方法排了一遍错,我也不知道是哪一步起效,所以就都放上来了。特别注意:报error 1935的错误原因可能不尽相同,比如我的报错开头为An error occurred,结尾为HRESULT:0x80070005。80070005 拒绝访问通常是权限问题,安装Visual C++无法写入文件夹或注册表(直接跳转第7步)

weixin_44427808的博客 1万+

二、Creo模型的功能函数 例如:模型(元件)的干涉........

【代码】模型(元件)的干涉。

行为艺术家Zzz的博客 613

Java 中的并发工具类详解:Semaphore、CountDownLatch 和 CyclicBarrier

Java 并发包提供了哪些并发工具类?比 synchronized 更加高级的各种同步结构各种线程安全的容器各种并发队列实现强大的 Executor 框架// 同步等待// 同步等待// 信号量1、信号量:Semaphore你可以想象一下这个场景,在车站、机场等出租车时,当很多空出租车就位时,为防止过度拥挤,调度员指挥排队等待坐车的队伍一次进来 5 个人上车,等这 5 个人坐车出发,再放进去下一批,这和 Semaphore 的工作原理有些类似。

swadian2008的博客 889

详解【异质图卷积网络 RGCN】回顾:图神经网络问题的三大处理步骤 | 从起源说起,RGCN核心公式解释,两种降低模型参数量/优化的方式,附核心代码实现讲解

本篇,我们深入分析和学习RGCN的原理以及为何要这么做。首先让我们来回顾对于图神经网络问题的三大处理步骤,可以说,这是该深度学习模型的基本理解,后续都是在深化其中的细节处理。然后以容易理解的方式,引出异质图卷积网络RGCN的由来,主要讲解其核心公式和论文中作者所提出的两种降低模型参数量/优化的处理办法,并给出基础分解以及块对角分解的核心实现代码讲解。最后附上RGCN源代码及说明。

追光者♂:记录、分享、总结、提升,现象级专栏《Python从入门到人工智能》作者,无惧黑暗,坚信曙光 1279

java并发工具类:CountdownLatch,CyclicBarrier,Semaphore

在jdk开发包java.util.concurrent中提供了几个非常有用的并发工具类: CountdownLatch CyclivcBarrier Semaphore 接下来一一解释其特性和用法: 1.CountdownLatch 1.1介绍 这是jdk文档的相关介绍,简而言之就是: CountDownLatch是一个同步工具类,用来协调多个线程之间的同步,或者说起到线程之间的通信(而不...

Alphr的博客 301

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Java并发工具类(一)CountDownLatch

Java并发工具类(一) CountDownLatch 在J.U.C并发包中提供了一些工具类,可以供我们在日常的开发中,根据不同的情况去进行一些相关的并发控制,具体的类有: CountDownLatch Semaphore Exchanger CyclicBarrier CountDownLatch 概念 计时器必须大于等于0,只是等于0的时候,计时器就是0,调用await()方法时,不会阻塞...

java界的小学生 967

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Java并发工具类之CountDownLatch

概述 CountDownLatch是一个同步工具类,用来协调多个线程之间的同步,或者说起到线程之间的通信的作用。CountDownLatch能够使一个线程在等待另外一些线程完成各自工作之后,再继续执行。使用一个计数器进行实现,计数器初始值为线程的数量。当每一个线程完成自己任务后,调用countDown()方法使计数器的值减1。当计数器的值为0时,表示所有的线程都已经完成一些任务,然后在CountDownLatch上等待的线程就可以恢复执行接下来的任务。 方法说明 public void await(

燕然一勒的博客 271

Java中的并发工具类:CountDownLatch、CyclicBarrier、Semaphore详解

适用于一个或多个线程等待其他线程完成操作后再继续执行的场景。:适用于多个线程相互等待,直到所有线程都到达某个屏障点后再继续执行的场景,且可以重复使用。Semaphore:适用于控制同时访问某个资源的线程数量,常用于资源池的管理。根据具体的需求选择合适的并发工具类,可以有效地协调多线程之间的同步,提高程序的并发性能。

吴晓斌的博客 958

java-并发工具类-CountDownLatch

并发工具类 CountDownLatch CountDownLatch允许一个或多个线程等待其他线程完成操作。可以实现join的功能且比join更加强大。 ​ CountDownLatch的构造函数接受一个int类型的等待线程数N, ​ 其中countDown方法,可以使N减一,await方法会阻塞当前线程,直到N为零。 CountDownLatch使用场景(需等待多个线程完成后,再执行本线程) ...

天涯共明月的博客 419

Java并发包下的CountDownLatch工具类

是 Java 中的一个并发工具类,用于协调多个线程之间的同步。其作用是让某一个线程等待多个线程的操作完成之后再执行。它可以使一个或多个线程等待一组事件的发生,而其他的线程则可以触发这组事件。

沉睡的猫的博客 253
上一篇: Java锁机制 浅析(二)之AQS
下一篇: Java并发工具类 CyclicBarrier
xychidy520_java
博客等级 码龄19年 5粉丝 16原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值