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原理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java实现从网上下载图片到本地的方法

    java实现从网上下载图片到本地的方法

    这篇文章主要介绍了java实现从网上下载图片到本地的方法,涉及java针对文件操作的相关技巧,非常简单实用,需要的朋友可以参考下
    2015-07-07
  • HashMap实现保存两个key相同的数据

    HashMap实现保存两个key相同的数据

    这篇文章主要介绍了HashMap实现保存两个key相同的数据操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • Spring Boot实现分布式系统中的服务发现和注册(最新推荐)

    Spring Boot实现分布式系统中的服务发现和注册(最新推荐)

    在本文中,我们深入探讨了Spring Boot如何实现分布式系统中的服务发现和注册,我们使用Eureka作为服务注册中心,Ribbon作为负载均衡器,Hystrix作为熔断器,成功地实现了服务发现、服务注册、负载均衡和服务熔断等功能,需要的朋友参考下吧
    2023-06-06
  • Java集合和数组的区别

    Java集合和数组的区别

    本文主要介绍了Java集合和数组的区别。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • Java Guava异步编程实践

    Java Guava异步编程实践

    今天咱们要聊的是Guava在异步编程中的应用,让我们搞清楚为什么要用Guava来处理异步任务,在Java的世界里,异步编程是个老话题了,但它依旧非常关键,它能让咱们的应用更高效,尤其是在处理那些耗时的I/O操作
    2023-12-12
  • 全面解读Java NIO(看这篇就够了)

    全面解读Java NIO(看这篇就够了)

    Java NIO是Java1.4之后推出来的一套IO接口,NIO提供了一种完全不同的操作方式, NIO支持面向缓冲区的、基于通道的IO操作,这篇文章主要介绍了Java NIO详解(看这篇就够了),需要的朋友可以参考下
    2023-05-05
  • Java中List转Map List实现的几种姿势

    Java中List转Map List实现的几种姿势

    本文主要介绍了Java中List转Map List实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06
  • XML解析四种方式代码示例详解

    XML解析四种方式代码示例详解

    这篇文章主要介绍了XML解析四种方式代码示例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-12-12
  • java 交换两个数据的方法实例详解

    java 交换两个数据的方法实例详解

    这篇文章主要介绍了java 交换两个数据的方法实例详解的相关资料,需要的朋友可以参考下
    2016-12-12
  • Java实现邮箱发送功能实例(阿里云邮箱推送)

    Java实现邮箱发送功能实例(阿里云邮箱推送)

    这篇文章主要给大家介绍了关于Java实现邮箱发送功能的相关资料,利用阿里云邮箱推送,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09

最新评论