Java使用CountDownLatch实现统计任务耗时

 更新时间:2023年06月01日 16:39:50   作者:海塔灯  
这篇文章主要为大家详细介绍了Java如何使用CountDownLatch实现统计任务耗时的功能,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下

1.什么是闭锁

在介绍本篇文章之前,先介绍下什么是闭锁?闭锁是一种同步的工具类,可以延迟线程的进度直到其到达终止状态,可以把闭锁看作是一扇门,在闭锁到达结束状态之前,这扇门一直是关闭的,并且没有任何线程能通过,当到达结束状态时,这扇门会打开允许所有线程通过。需要注意的是,当闭锁到达结束状态后,将不会再改变状态,因此这扇门将会永远保持打开状态。闭锁可以用来确保某些任务直到其他任务都完成才继续执行。

2.闭锁的使用场景

闭锁在开发过程中的用途非常广,总结下来主要有以下几个场景会用到闭锁

2.1.确保某个计算在资源初始后再继续执行

在这种场景下我们可以使用二元闭锁,二元闭锁包括两个状态,可以用来表示“资源已经被初始化”,而所有需要用到资源R的操作都必须在这个闭锁上等待。例如我们需要加载一个配置文件,根据配置文件去做一些操作就可以使用这种闭锁的方式;

2.2.确保某个服务在其依赖的所有其他服务都启动之后才启动

每个服务都有一个相关的二元闭锁。当启动服务S时,将首先在S依赖的其他服务闭锁上等待,在所有依赖的服务都启动后会释放闭锁S,这样其他依赖S的服务才能继续执行。例如在Android的Aidl服务绑定的时候,客户端绑定服务端获取Binder对象时,大概会有个30ms(不精确)的延迟,如果设计SDK的时候,绑定服务端和启动其他调用服务端的操作又是并行的情况下,就会出现binder为空的情况,这里就可以使用闭锁来实现。具体的实现手法有兴趣的话下次单独出一篇文章介绍。

2.3.等待直到某个操作的所有参与者都就绪再继续执行

这里举一个大家很熟悉的例子,王者荣耀的匹配,每次匹配都需要你自己的队友和对面的对手在内的所有玩家都就绪后才能开始游戏,不然就会出现少打多的滑稽情况了。这种场景下,当所有的玩家都准备就绪时,闭锁将会达到结束状态。

3. CountDownLatch

CountDownLatch 是闭锁的一种实现,可以在我们上面的各种场景中使用,它可以使一个或者多个线程等待一组事件发生,闭锁状态包括一个计数器,该计数器被初始化为一个正数,表示需要等待的事件数量,countDown方法递减计数器,表示有一个事件已经发生了,而await方法会一直阻塞直到计数器达到零。这表示所有等待的事件都已经发生,如果计数器的值非零,那么await会一直阻塞直到计数器为零,或者等待中的线程中断,或等待超时

3.1 使用CountDownLatch统计多个工作线程执行的耗时

大致原理是使用两个闭锁,一个开始门,一个结束门,开始门计数器初始值为1,结束门的初始值为工作线程的数量,所有工作线程首先要做的事情就是在开始门上等待,从而确保所有线程都就绪后才开始执行,每个线程套作的最后一件事情是调用结束门的countDown方法减一。demo代码如下所示:

  public static long timeTasks(int nThreads, final Runnable task) throws InterruptedException {
        final CountDownLatch startGate = new CountDownLatch(1);
        final CountDownLatch endGate = new CountDownLatch(nThreads);

        for (int i = 0; i < nThreads; i++){
            Thread t = new Thread(){
                public void run(){
                    try {
                        System.out.println("startGate before========");
                        startGate.await();
                        System.out.println("startGate after========");
                        try{
                            task.run();
                        }finally {
                            endGate.countDown();
                            System.out.println("endGate.countDown()========");
                        }
                    } catch (InterruptedException ignored) {}
                }
            };

            t.start();
        }

        long start = System.nanoTime();
        System.out.println("start========" + start);
        startGate.countDown();
        System.out.println("endGate before========");
        endGate.await();
        long end = System.nanoTime();
        System.out.println("end========" + end);
        return end-start;
    }

注意:上面的代码中,也许读者会发现为啥要在timeTask()中使用闭锁,而不是线程一创建后就立即启动,因为如果在创建线程后就立即启动他们,那么先启动的线程将“领先”后启动的线程,并且活跃的线程数量会随着时间的推移而增加或者减少,竞争程度也在不断发生变化。启动门将使得主线程能够同时释放所有工作线程,而结束门则使主线程能够等待最后一个线程执行完成,而不是顺序地等待每个线程执行完成

到此这篇关于Java使用CountDownLatch实现统计任务耗时的文章就介绍到这了,更多相关Java CountDownLatch内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • jdk中密钥和证书管理工具keytool常用命令详解

    jdk中密钥和证书管理工具keytool常用命令详解

    keytool JAVA是个密钥和证书管理工具。它使用户能够管理自己的公钥/私钥对及相关证书,用于(通过数字签名)自我认证(用户向别的用户/服务认证自己)或数据完整性以及认证服务
    2014-01-01
  • 分隔List集合,按指定大小,将集合分成多个的方法

    分隔List集合,按指定大小,将集合分成多个的方法

    下面小编就为大家带来一篇分隔List集合,按指定大小,将集合分成多个的方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-03-03
  • ssm项目改造spring boot项目完整步骤

    ssm项目改造spring boot项目完整步骤

    Spring Boot现在已经成为Java开发领域的一颗璀璨明珠,它本身是包容万象的,可以跟各种技术集成,下面这篇文章主要给大家介绍了关于ssm项目改造spring boot项目的相关资料,需要的朋友可以参考下
    2023-04-04
  • MyBatis实现配置加载的步骤

    MyBatis实现配置加载的步骤

    本文主要介绍了MyBatis实现配置加载的步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05
  • Java实现邮箱发送功能实例(阿里云邮箱推送)

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

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

    java内部类之成员内部类、局部内部类和匿名内部类用法及说明

    这篇文章主要介绍了java内部类之成员内部类、局部内部类和匿名内部类的用法及说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • Mybatis关联查询结果集对象嵌套的具体使用

    Mybatis关联查询结果集对象嵌套的具体使用

    在查询时经常出现一对多”的关系,所有会出现嵌套对象的情况,本文主要介绍了Mybatis关联查询结果集对象嵌套的具体使用,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • Spring Boot详解配置文件的用途与用法

    Spring Boot详解配置文件的用途与用法

    SpringBoot项目是一个标准的Maven项目,它的配置文件需要放在src/main/resources/下,其文件名必须为application,其存在两种文件形式,分别是properties和yaml(或者yml)文件
    2022-06-06
  • Java Set集合及其子类HashSet与LinkedHashSet详解

    Java Set集合及其子类HashSet与LinkedHashSet详解

    这篇文章主要介绍了Java Set集合及其子类HashSet与LinkedHashSet详解,文章通过Set集合存储原理展开文章主题相关介绍,感兴趣的小伙伴可以参考一下
    2022-06-06
  • Java 注解学习笔记

    Java 注解学习笔记

    这篇文章主要介绍了Java 注解的相关资料,帮助大家更好的理解和学习使用Java,感兴趣的朋友可以了解下
    2021-03-03

最新评论