Java并发编程同步器CountDownLatch

 更新时间:2022年04月15日 16:55:06   作者:派大大大星   
这篇文章主要介绍了Java并发编程同步器CountDownLatch,文章基于Java并发编程的相关资料展开具有一定的参考价值,需要的小伙伴可以参考一下

CountDownLatch

在日常开发中经常会遇到需要在主线程中开启多个线程去并行执行任务,并且主线程需要等待所有子线程执行完毕后再进行汇总的场景。在 CountDownLatch 出现之前般都使用线程的join()方法来实现这一点,但是 join 方法不够灵活,不能够满足不同场景的需要,所以 JDK 开发组提供了 CountDownLatch 这个类,我们前面介绍的例子使用 CoumtDownLatch 会更优雅。

使用CountDownLatch 的代码如下:

package LockSupportTest;

import java.util.concurrent.CountDownLatch;

public class JoinCountDownLatch {

    private static volatile CountDownLatch countDownLatch = new CountDownLatch(2);

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

        Thread threadOne = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                    System.out.println("child threadOne over!");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    countDownLatch.countDown();
                }
            }
        });
        
        Thread threadTwo = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                    System.out.println("child threadOne over!");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    countDownLatch.countDown();
                }
            }
        });

        threadOne.start();
        threadTwo.start();
        System.out.println("wait all child thread over!!!");
        countDownLatch.await();
        System.out.println("all child thread over!");
    }

}

image.png

在如上代码中,创建了一个 CountDownLatch 实例,因为有两个子线程所以构造函数的传参为2。主线程调用countDownLatch.await()方法后会被阻塞。子线程执行完毕后调用 countDownLatch.countDown()方法让 countDownLatch 内部的计数器减1,所有子线程执行完毕并调用 countDown()方法后计数器会变为0,这时候主线程的await()方法才会返回。其实上面的代码还不够优雅,在项目实践中一般都避免直接操作线程,而是使用 ExceutorService线程池来管理,使用ExcsuIwsnise时传递的参数是 Runable 或者 Callable对象,这时候你没有办法直接调用这些线程的join()方法,这就需要选择使用CountDownLatch了。

将上面的代码修改为:

package LockSupportTest;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class JoinCountDownLatch2 {

    private static volatile CountDownLatch countDownLatch = new CountDownLatch(2);

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

        ExecutorService executorService = Executors.newFixedThreadPool(2);
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                    System.out.println("child threadOne over!");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    countDownLatch.countDown();
                }
            }
        });
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                    System.out.println("child threadTwo over!");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    countDownLatch.countDown();
                }
            }
        });
        System.out.println("wait all child thread over!!!");
        countDownLatch.await();
        System.out.println("all child thread over!");
        executorService.shutdown();
    }

}

image.png

最后总结一下CountDownLatch与join()的区别。一个区别是,调用一个子线程的join()方法后,该线程会一直被阻塞直到子线程运行完毕,而 CountDownLatch 则使用计数器来允许子线程运行完毕或者在运行中递减计数,也就是 CountDownLach 可以在子线程运行的任何时候让 await() 方法返回而不一定必须等到线程结東。另外,使用线程池来管理线程时一般都是直接添加 Runable 到线程池,这时候就没有办法再调用线程的 join 方法了,就是说 counDownLatch 相比 join 方法让我们对线程同步有更灵活的控制。

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

相关文章

  • Redis之GEO存储地理位置信息的使用

    Redis之GEO存储地理位置信息的使用

    在外卖软件中的附近的美食店铺、外卖小哥的距离,打车软件附近的车辆,交友软件中附近的小姐姐。我们都可以利用redis的GEO地理位置计算得出。本文就来详细的介绍一下
    2021-10-10
  • 浅谈@Aspect@Order各个通知的执行顺序

    浅谈@Aspect@Order各个通知的执行顺序

    这篇文章主要介绍了@Aspect@Order各个通知的执行顺序,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02
  • 浅谈Java中的高精度整数和高精度小数

    浅谈Java中的高精度整数和高精度小数

    本篇文章主要介绍了浅谈Java中的高精度整数和高精度小数,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • JavaFx实现拼图游戏

    JavaFx实现拼图游戏

    这篇文章主要为大家详细介绍了JavaFx实现拼图游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-09-09
  • java策略枚举:消除在项目里大批量使用if-else的优雅姿势

    java策略枚举:消除在项目里大批量使用if-else的优雅姿势

    这篇文章主要给大家介绍了关于Java彻底消灭if-else的8种方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2021-06-06
  • Java并发编程之ReentrantLock解析

    Java并发编程之ReentrantLock解析

    这篇文章主要介绍了Java并发编程之ReentrantLock解析,ReentrantLock内容定义了一个抽象类Sync,继承自AQS,而不是自己去继承AQS,所有对ReentrantLock的操作都会转化为对Sync的操作,需要的朋友可以参考下
    2023-12-12
  • 详解Java编程中Annotation注解对象的使用方法

    详解Java编程中Annotation注解对象的使用方法

    这篇文章主要介绍了Java编程中Annotation注解对象的使用方法,注解以"@注解名"的方式被编写,与类、接口、枚举是在同一个层次,需要的朋友可以参考下
    2016-03-03
  • Java HttpClient-Restful工具各种请求高度封装提炼及总结

    Java HttpClient-Restful工具各种请求高度封装提炼及总结

    这篇文章主要介绍了Java HttpClient-Restful工具各种请求高度封装提炼及总结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-10-10
  • SpringMvc定制化深入探究原理

    SpringMvc定制化深入探究原理

    SpringMVC是一种基于Java,实现了Web MVC设计模式,请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将Web层进行职责解耦,这篇文章主要介绍了SpringMvc定制化原理
    2022-10-10
  • SpringBoot中整合MyBatis-Plus的方法示例

    SpringBoot中整合MyBatis-Plus的方法示例

    这篇文章主要介绍了SpringBoot中整合MyBatis-Plus的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09

最新评论