org.springframework.util.StopWatch:简洁的耗时统计小工具

想知道一个代码块执行耗时多久,通常做法是执行前记录当前时间A,执行后用当前时间减去A就是耗时了。spring库中有个统计耗时的小工具:StopWatch类,它可以帮我们做这些事情,甚至做得更好,咱们直接上代码实战吧:

创建项目

我这里用的是Intellij IDEA社区版,用maven创建一个Java工程,如下图所示:

添加依赖

在pom.xml中添加spring core的依赖,另外,为了看到更丰富的对象信息,我们把fastjson也加入进来,如下:

<properties>
        <!-- spring版本号 -->
        <spring.version>4.0.2.RELEASE</spring.version>
        <!-- fastjson版本号 -->
        <fastjson.version>1.2.39</fastjson.version>
    </properties>
    <dependencies>
        <!-- spring核心包 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!-- fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>${fastjson.version}</version>
        </dependency>
    </dependencies>

模拟耗时的方法

在实际项目中,我们在调用本地方法,操作数据库,发起远程调用等场景都有可能耗时较长,所以此处做三个方法来模拟这些场景,如下,这个类的名字是StopWatchDemo:

/**
     * 延时的方法
     * @param time 延时时常,单位毫秒
     */
    private static void delay(long time){
        try{
            Thread.sleep(time);
        }catch(InterruptedException e){
            e.printStackTrace();
        }
    }

    /**
     * 假设这个方法在执行本地调用,耗时100毫秒
     */
    private void executeNative(){
        delay(100);
    }

    /**
     * 假设这个方法在执行数据库操作,耗时200毫秒
     */
    private void executeDB(){
        delay(200);
    }

    /**
     * 假设这个方法在执行远程调用,耗时300毫秒
     */
    private void executeRPC(){
        delay(300);
    }

用StopWatch类统计耗时

执行每个方法,并且统计这些方法耗时的代码如下,不多说了,看注释就好:

StopWatchDemo demo = new StopWatchDemo();

        //起个名字,在最后面统计信息中会打印出来
        StopWatch stopWatch = new StopWatch("stopwatch test");

        //记录本地方法的耗时
        stopWatch.start("执行本地方法");
        demo.executeNative();
        stopWatch.stop();

        //记录数据库操作的耗时
        stopWatch.start("执行数据库操作");
        demo.executeDB();
        stopWatch.stop();

        //记录数远程调用耗时
        stopWatch.start("执行远程调用");
        demo.executeRPC();
        stopWatch.stop();

        //打印一份格式化好的汇总统计信息
        System.out.println(stopWatch.prettyPrint());

        System.out.println("\n");

        //打印统计名称和总的耗时
        System.out.println(stopWatch.shortSummary());

        System.out.println("\n");

        //一共执行了三段统计,stopWatch.getTaskInfo()返回的数组中就是每段的信息,这里用fastjson转成字符串便于查看
        System.out.println(JSON.toJSON(stopWatch.getTaskInfo()));

执行结果

代码的执行结果如下,可以看到prettyPrint()返回的信息是格式化好的汇总数据,包含了每段耗时以及所占整体的百分比,让人对大致情况一目了然,shortSummary()返回的是名称和总耗时,stopWatch.getTaskInfo()返回了一个数组,里面是每一段统计的名称和耗时:

StopWatch 'stopwatch test': running time (millis) = 612
-----------------------------------------
ms     %     Task name
-----------------------------------------
00106  017%  执行本地方法
00204  033%  执行数据库操作
00302  049%  执行远程调用



StopWatch 'stopwatch test': running time (millis) = 612


[{"timeSeconds":0.106,"taskName":"执行本地方法","timeMillis":106},{"timeSeconds":0.204,"taskName":"执行数据库操作","timeMillis":204},{"timeSeconds":0.302,"taskName":"执行远程调用","timeMillis":302}]

注意事项

在阅读StopWatch的源码时,发现有两点需要注意: 1. 多个耗时的分段信息是存储在LinkedList集合中的,非线程安全,而且有很多成员变量,所以不能在多线程中使用; 2. StopWatch类的作者如下图所示,Rod Johnson:Spring Framework创始人、音乐学博士~~

至此,简洁易用的StopWatch就介绍完毕了,希望它能在开发调试和查找问题时祝您一臂之力。

Demo工程源码可以在我的git上获取:git@github.com:zq2599/blog_demos.git 里面有多个工程,本次实战对应的工程如下图红框所示:

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java技术栈

Spring Boot 2.x 启动全过程源码分析(全)

上篇《Spring Boot 2.x 启动全过程源码分析(一)入口类剖析》我们分析了 Spring Boot 入口类 SpringApplication 的源码...

1924
来自专栏Linux驱动

42.Linux应用调试-初步制作系统调用(用户态->内核态)

1首先来讲讲应用程序如何实现系统调用(用户态->内核态)? 我们以应用程序的write()函数为例: 1)首先用户态的write()函数会进入glibc库,里面...

1985
来自专栏杨建荣的学习笔记

最简单的web服务器实现(一)(r4笔记第68天)

tomcat作为web服务器,想必大家做过web开发的都离不开tomcat了,值得庆幸的是tomcat也是开放源代码的,最近准备好好琢磨琢磨tomcat的源码,...

3435
来自专栏圣杰的专栏

ABP入门系列(4)——创建应用服务

一、解释下应用服务层 应用服务用于将领域(业务)逻辑暴露给展现层。展现层通过传入DTO(数据传输对象)参数来调用应用服务,而应用服务通过领域对象来执行相应的业务...

2347
来自专栏码代码的陈同学

jstack是如何获取threaddump的?

JDK提供了许多命令行工具用于监视JVM,让我们可以了解其异常堆栈、GC日志、threaddump、heapdump等信息。一时好奇,想看看jstack是如何实...

1155
来自专栏Linux驱动

35.Linux-分析并制作环形缓冲区

在上章34.Linux-printk分析、使用printk调试驱动里讲述了:  printk()会将打印信息存在内核的环形缓冲区log_buf[]里, 可以通...

2008
来自专栏xingoo, 一个梦想做发明家的程序员

《深入浅出Nodejs》—— 读后总结

这一个月过去了三分之二,加上之前看过这本书三分之一,这才算是看完。 虽然看完一遍,但是这本书内容很深,以后肯定是还要继续翻阅的..... 什么是Node...

1785
来自专栏我是攻城师

简述ElasticSearch里面复杂关系数据的存储方式

4357
来自专栏张戈的专栏

Linux系统下MongoDB的简单安装与基本操作

Mongo DB ,是目前在 IT 行业非常流行的一种非关系型数据库(NoSql),其灵活的数据存储方式,备受当前 IT 从业人员的青睐。Mongo DB 很好...

3223
来自专栏aCloudDeveloper

UNIX环境高级编程笔记之高级I/O

  本章说明了很多高级I/O功能: 非阻塞I/O——发一个I/O操作,不使其阻塞,记录锁,STREAMS机制 I/O多路转接——select和poll函数 re...

1907

扫码关注云+社区