Java并发编程之CountDownLatch原理详解

 更新时间:2023年12月11日 08:48:16   作者:程光CS  
这篇文章主要介绍了Java并发编程之CountDownLatch原理详解,CountDownLatch类中使用了一个继承自AQS的共享锁Sync对象,构造CountDownLatch对象时会将传入的线程数值设为AQS的state值,需要的朋友可以参考下

一、CountDownLatch介绍

在日常开发中经常会遇到需要在主线程中开启多个线程去并行执行任务,并且主线程需要等待所有子线程执行完毕后再进行汇总的场景。

在 CountDownLatch 出现之前一般都使用线程的join()方法来实现这一点,但是 join 方法不够灵活,不能够满足不同场景的需要,所以JDK开发组提供了 CountDownLatch 这个类,使用CountDownLatch 会更优雅。

并且CountDownLatch 可以在子线程的任何位置让 await 方法返回而不一定必须线程结束,这比join更加灵活。使用 CountDownLatch 的代码如下:

public static void main(String[] args) throws InterruptedException {
    //内部sync同步器的state值设为3
    CountDownLatch countDownLatch = new CountDownLatch(3);

    for (int i = 1;i <= 3;i++) {
        new Thread(() -> {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                System.out.println("目标代码块运行完毕");
                //每调用一次countDown()内部调用releaseShared(1)都会使state值减一
                countDownLatch.countDown();
            }
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("线程结束");
        }).start();
    }
    System.out.println("所有线程已启动");
    //主线程调用await()方法后就会进入阻塞,直到所有线程调用了countDown()使state值被减为0,或者主线程被中断,才会从阻塞返回
    countDownLatch.await();
    System.out.println("所有线程目标代码块已运行完毕");
}

二、CountDownLatch原理

CountDownLatch类中使用了一个继承自AQS的共享锁Sync对象,构造CountDownLatch对象时会将传入的线程数值设为AQS的state值

当一个线程结束运行调用countDown()方法时,内部调用releaseShared(1)时调用Sync中重写的钩子方法tryReleaseShared()都会使state值减一,当被state被减为0后tryReleaseShared才会返回true,继而调用doReleaseShared唤醒同步队列中被阻塞的线程

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

主线程调用await()方法后就会进入阻塞,其内部调用的acquireSharedInterruptibly方法,只有当钩子方法tryAcquireShared返回值>=0时才能拿到锁,而Sync中重写的tryAcquireShared只有当state为0才会返回1,否则返回-1,因此只有到最后一个线程调用了countDown()使state值被减为0继而唤醒同步队列中阻塞的主线程,或者主线程被中断,才会从阻塞返回。

到此这篇关于Java并发编程之CountDownLatch原理详解的文章就介绍到这了,更多相关CountDownLatch原理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Guava反射工具使用示例详解

    Guava反射工具使用示例详解

    这篇文章主要为大家介绍了Guava反射工具使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12
  • StringBuffer与StringBuilder底层扩容机制与常用方法

    StringBuffer与StringBuilder底层扩容机制与常用方法

    这篇文章主要给大家介绍了StringBuffer、StringBuilder底层扩容机制与常用方法,有感兴趣的小伙伴跟着小编一起来学习吧
    2023-07-07
  • spring cloud gateway转发服务报错的解决

    spring cloud gateway转发服务报错的解决

    这篇文章主要介绍了spring cloud gateway转发服务报错的解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • Java面试题冲刺第二十三天--算法(2)

    Java面试题冲刺第二十三天--算法(2)

    这篇文章主要为大家分享了最有价值的三道关于算法的面试题,涵盖内容全面,包括数据结构和算法相关的题目、经典面试编程题等,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • Java使用LinkedHashMap进行分数排序

    Java使用LinkedHashMap进行分数排序

    这篇文章主要介绍了Java使用LinkedHashMap进行分数排序的相关代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05
  • Nacos封装通用HttpClient详解

    Nacos封装通用HttpClient详解

    这篇文章主要介绍了Nacos封装通用HttpClient用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • mybatis多对多关联实战教程(推荐)

    mybatis多对多关联实战教程(推荐)

    下面小编就为大家带来一篇mybatis多对多关联实战教程(推荐)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10
  • Java观察者模式的深入了解

    Java观察者模式的深入了解

    这篇文章主要为大家介绍了Java观察者模式,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-01-01
  • Java中缀表达式转后缀表达式实现方法详解

    Java中缀表达式转后缀表达式实现方法详解

    这篇文章主要介绍了Java中缀表达式转后缀表达式实现方法,结合实例形式分析了Java中缀表达式转换成后缀表达式的相关算法原理与具体实现技巧,需要的朋友可以参考下
    2019-03-03
  • Java guava monitor监视器线程的使用详解

    Java guava monitor监视器线程的使用详解

    工作中的场景中是否存在类似这样的场景,需要提交的线程在某个触发条件下执行。本文主要就是使用guava中的monitor来优雅的实现带监视器的线程
    2021-11-11

最新评论