Java并发编程之CountDownLatch原理详解
一、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原理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
Java8 CompletableFuture 异步执行操作
CompletableFuture是java8提供的基于异步操作的封装,日常开发中经常会用到,接下来通过本文给大家介绍Java8 CompletableFuture 异步执行操作,感兴趣的朋友一起看看吧2021-06-06
在Spring Boot中使用swagger-bootstrap-ui的方法
这篇文章主要介绍了在Spring Boot中使用swagger-bootstrap-ui的方法,需要的朋友可以参考下2018-01-01
Spring中的@ModelAttribute模型属性绑定详解
这篇文章主要介绍了Spring中的@ModelAttribute模型属性绑定详解,@ModelAttribute用于将方法参数或返回值绑定到Model属性上,并公开给Web视图,支持使用@RequestMapping注释的Controller类,需要的朋友可以参考下2024-02-02
利用ClasserLoader实现jar包加载并调用里面的方法
classloader即是类加载,虚拟机把描述类的数据从class字节码文件加载到内存,并对数据进行检验、转换解析和初始化,了解java的类加载机制,可以快速解决运行时的各种加载问题并快速定位其背后的本质原因,本文介绍了如何利用ClasserLoader来实现jar包加载并调用里面的方法2024-09-09
Spring Boot使用AOP实现REST接口简易灵活的安全认证的方法
这篇文章主要介绍了Spring Boot使用AOP实现REST接口简易灵活的安全认证的方法,非常具有实用价值,需要的朋友可以参考下2018-11-11


最新评论