• 一、背景

    有时我们在做开发的时候需要记录每个任务执行时间,或者记录一段代码执行时间,最简单的方法就是打印当前时间与执行完时间的差值,一般我们检测某段代码执行的时间,都是以如下方式来进行的:

    public static void main(String[] args) {  Long startTime = System.currentTimeMillis();  // 你的业务代码  Long endTime = System.currentTimeMillis();  Long elapsedTime = (endTime - startTime) / 1000;  System.out.println("该段总共耗时:" + elapsedTime + "s");}

    事实上该方法通过获取执行完成时间与执行开始时间的差值得到程序的执行时间,简单直接有效,但想必写多了也是比较烦人的,尤其是碰到不可描述的代码时,会更加的让人忍不住多写几个bug聊表敬意,而且如果想对执行的时间做进一步控制,则需要在程序中很多地方修改。

    此时会想是否有一个工具类,提供了这些方法,刚好可以满足这种场景?

    我们可以利用已有的工具类中的秒表,常见的秒表工具类有 org.springframework.util.StopWatch、org.apache.commons.lang.time.StopWatch以及谷歌提供的guava中的秒表(这个我没怎么用过)

    这里重点讲下基于spring、Apache的使用

    二、spring 用法

    2.1 初遇

    StopWatch 是位于 org.springframework.util 包下的一个工具类,通过它可方便的对程序部分代码进行计时(ms级别),适用于同步单线程代码块。简单总结一句,Spring提供的计时器StopWatch对于秒、毫秒为单位方便计时的程序,尤其是单线程、顺序执行程序的时间特性的统计输出支持比较好。

    也就是说假如我们手里面有几个在顺序上前后执行的几个任务,而且我们比较关心几个任务分别执行的时间占用状况,希望能够形成一个不太复杂的日志输出,StopWatch提供了这样的功能。而且Spring的StopWatch基本上也就是仅仅为了这样的功能而实现。

    想要使用它,首先你需要在你的 Maven 中引入 Spring 核心包,当然 Spring MVC 和 Spring Boot 都已经自动引入了该包:

    <!-- https://mvnrepository.com/artifact/org.springframework/spring-core --><dependency>    <groupId>org.springframework</groupId>    <artifactId>spring-core</artifactId>    <version>${spring.version}</version></dependency>

    对一切事物的认知,都是从使用开始,那就先来看看它的用法,会如下所示:

    public static void main(String[] args) throws InterruptedException {    StopWatch stopWatch = new StopWatch();
    
        // 任务一模拟休眠3秒钟    stopWatch.start("TaskOneName");    Thread.sleep(1000 * 3);    System.out.println("当前任务名称:" + stopWatch.currentTaskName());    stopWatch.stop();
    
        // 任务一模拟休眠10秒钟    stopWatch.start("TaskTwoName");    Thread.sleep(1000 * 10);    System.out.println("当前任务名称:" + stopWatch.currentTaskName());    stopWatch.stop();
    
        // 任务一模拟休眠10秒钟    stopWatch.start("TaskThreeName");    Thread.sleep(1000 * 10);    System.out.println("当前任务名称:" + stopWatch.currentTaskName());    stopWatch.stop();
    
        // 打印出耗时    System.out.println(stopWatch.prettyPrint());    System.out.println(stopWatch.shortSummary());    // stop后它的值为null    System.out.println(stopWatch.currentTaskName()); 
    
        // 最后一个任务的相关信息    System.out.println(stopWatch.getLastTaskName());    System.out.println(stopWatch.getLastTaskInfo());
    
        // 任务总的耗时  如果你想获取到每个任务详情(包括它的任务名、耗时等等)可使用    System.out.println("所有任务总耗时:" + sw.getTotalTimeMillis());    System.out.println("任务总数:" + sw.getTaskCount());    System.out.println("所有任务详情:" + sw.getTaskInfo());}

    如图所示,StopWatch 不仅正确记录了上个任务的执行时间,并且在最后还可以给出精确的任务执行时间(纳秒级别)和耗时占比,这或许就会比我们自己输出要优雅那么一些。

    2.2 源码

    老规矩,由浅入深。看完用法,我们来看看源码。先看下组成 StopWatch 的属性

    public class StopWatch {    /**  * 本实例的唯一 Id,用于在日志或控制台输出时区分的。  */    private final String id;    /**  * 是否保持一个 taskList 链表  * 每次停止计时时,会将当前任务放入这个链表,用以记录任务链路和计时分析  */ private boolean keepTaskList = true;   /**  * 任务链表  * 用来存储每个task的信息, taskInfo由taskName 和 totoalTime组成  */    private final List<StopWatch.TaskInfo> taskList;    /**  * 当前任务的开始时间  */    private long startTimeMillis;    /**  *   */    private boolean running;    /**  * 当前任务名称  */    private String currentTaskName;    /**  * 最后一个任务的信息  */    private StopWatch.TaskInfo lastTaskInfo;    /**  * 任务总数  */    private int taskCount;    /**  * 程序执行时间  */    private long totalTimeMillis;    ...}

    接下来,我们看一下StopWatch类的构造器和一些关键方法

    方法 说明
    new StopWatch() 构建一个新的秒表,不开始任何任务。
    new StopWatch(String id) 创建一个指定了id的StopWatch
    String getId() 返回此秒表的ID
    void start(String taskName) 不传入参数,开始一个无名称的任务 的计时。传入String类型的参数来开始指定任务名的任务计时
    void stop() 停止当前任务的计时
    boolean isRunning() 是否正在计时某任务
    String currentTaskName() 当前正在运行的任务的名称(如果有)
    long getTotalTimeMillis() 所有任务的总体执行时间(毫秒单位)
    double getTotalTimeSeconds() 所有任务的总时间(以秒为单位)
    String getLastTaskName() 上一个任务的名称
    long getLastTaskTimeMillis() 上一个任务的耗时(毫秒单位)
    int getTaskCount() 定时任务的数量
    String shortSummary() 总运行时间的简短描述
    String prettyPrint() 优美地打印所有任务的详细耗时情况

    2.3 注意事项

    • StopWatch对象不是设计为线程安全的,并且不使用同步。
    • 一个StopWatch实例一次只能开启一个task,不能同时start多个task
    • 在该task还没stop之前不能start一个新的task,必须在该task stop之后才能开启新的task
    • 若要一次开启多个,需要new不同的StopWatch实例

    三、apache 用法

    StopWath是 apache commons lang3 包下的一个任务执行时间监视器,与我们平时常用的秒表的行为比较类似,我们先看一下其中的一些重要方法:

    方法 说明
    new StopWatch() 构建一个新的秒表,不开始任何任务。
    static StopWatch createStarted()
    void start() 开始计时
    void stop() 停止当前任务的计时
    void reset() 重置计时
    void split() 设置split点
    void unsplit()
    void suspend() 暂停计时, 直到调用resume()后才恢复计时
    void resume() 恢复计时
    long getTime() 统计从start到现在的计时
    long getTime(final TimeUnit timeUnit)
    long getNanoTime()
    long getSplitTime() 获取从start 到 最后一次split的时间
    long getSplitNanoTime()
    long getStartTime()
    boolean isStarted()
    boolean isSuspended()
    boolean isStopped()
    <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 --><dependency>    <groupId>org.apache.commons</groupId>    <artifactId>commons-lang3</artifactId>    <version>3.6</version></dependency>

    Apache提供的这个任务执行监视器功能丰富强大,灵活性强,如下经典实用案例:

    public static void main(String[] args) throws InterruptedException {    //创建后立即start,常用    StopWatch watch = StopWatch.createStarted();
    
        // StopWatch watch = new StopWatch();    // watch.start();
    
        Thread.sleep(1000);    System.out.println(watch.getTime());    System.out.println("统计从开始到现在运行时间:" + watch.getTime() + "ms");
    
        Thread.sleep(1000);    watch.split();    System.out.println("从start到此刻为止的时间:" + watch.getTime());    System.out.println("从开始到第一个切入点运行时间:" + watch.getSplitTime());    Thread.sleep(1000);    watch.split();    System.out.println("从开始到第二个切入点运行时间:" + watch.getSplitTime());
    
        // 复位后, 重新计时    watch.reset();    watch.start();    Thread.sleep(1000);    System.out.println("重新开始后到当前运行时间是:" + watch.getTime());
    
        // 暂停 与 恢复    watch.suspend();    System.out.println("暂停2秒钟");    Thread.sleep(2000);
    
        // 上面suspend,这里要想重新统计,需要恢复一下    watch.resume();    System.out.println("恢复后执行的时间是:" + watch.getTime());
    
        Thread.sleep(1000);    watch.stop();
    
        System.out.println("花费的时间》》" + watch.getTime() + "ms");    // 直接转成s    System.out.println("花费的时间》》" + watch.getTime(TimeUnit.SECONDS) + "s");}

    四、最后

    很多时候,写代码也是一种艺术,而借助这种实用工具我就觉得艺术感更强些。希望我们能有追求更加美好事物的心,这点对于接纳新知识特别重要。此处推荐这个监视器来代替之前的的使用,能让小伙伴们更加灵活的分析你的代码~

StopWatch统计耗时相关推荐

  1. 用StopWatch统计耗时,比System.currentTimeMillis好用

    平时项目中统计耗时都用System.currentTimeMillis,最近看到一个spring-StopWatch统计耗时,其用法简单明了,比传统统计耗时方法好用. StopWatch 的内部是通过 ...

  2. 别再用 System.currentTimeMillis 统计耗时了,太 Low,试试 Spring Boot 源码在用的 StopWatch吧,够优雅

    大家好,我是二哥呀! 昨天,一位球友问我能不能给他解释一下 @SpringBootApplication 注解是什么意思,还有 Spring Boot 的运行原理,于是我就带着他扒拉了一下这个注解的源 ...

  3. 使用StopWatch计算耗时

    一.传统计算耗时方式 一般采用 System.currentTimeMillis() 来获取时间,然后打印当前时间与任务开始执行时间的差值. 记录开始时间点 记录结束时间点 输出当前时间与任务开始执行 ...

  4. java StopWatch计算耗时毫秒数

    java 计算耗时毫秒数的方法: StopWatch stopWatch = new StopWatch("下载文件耗时");stopWatch.start();....//各种下 ...

  5. 统计方法耗时的三种秘法

    统计方法耗时的三种秘法 1. 统计方法耗时的三种秘法 1.1 `System.currentTimeMillis()` 统计法 1.2 `org.springframework.util.StopWa ...

  6. jsp中java代码无效_来杯咖啡,教你如何优雅的在java中统计代码块耗时

    推荐阅读: Sping源码+Redis+Nginx+MySQL等七篇实战技术文档,阿里大佬推荐 阿里内部:2020年全技术栈文档+PPT分享,(万粉总结,回馈粉丝) 在我们的实际开发中,多多少少会遇到 ...

  7. 如何优雅的在java中统计代码块耗时

    在我们的实际开发中,多多少少会遇到统计一段代码片段的耗时的情况,我们一般的写法如下 long start = System.currentTimeMillis(); try {// .... 具体的代 ...

  8. Golang 打印耗时统计、纳秒级耗时统计(统计函数执行时间)

    文章目录 Golang 打印耗时统计 普通demo 利用defer的简洁方法 利用defer更优雅的方法 纳秒级耗时统计 time.Now().UnixNano() Golang 打印耗时统计 参考U ...

  9. AOP面向切面编程之全局日志打印/统计接口耗时

    目录 一.什么是AOP 二.AOP使用场景 三.使用AOP的好处 四.先举个例子理解AOP面向切面编程 五.Spring5.X的AOP切入点表达式有这些种写法 六.实战基于Spring的AOP快速实现 ...

最新文章

  1. GitHub Checks API帮助应用实现进一步的持续集成
  2. python基础:week three
  3. matlab程序设计实践,MATLAB程序设计实践(第二题)
  4. 【LeetCode】390. 消除游戏
  5. 舒适的路线(codevs 1001)
  6. python中config命令_【Python】 配置解析ConfigParser 命令行参数解析optparser
  7. 单片机学校实训老师上课需要的工具以及源码分享
  8. yum用法及程序编译安装
  9. 二分查找(java)
  10. PAT甲级1001 字符串处理
  11. 走向.NET架构设计—第四章—业务层分层架构(中篇)
  12. 探访蔚来合肥工厂:是ES8与ES6生产基地 能年产10万台
  13. #paragma详解
  14. java jdk 9 64位下载地址_jdk9.0官方下载|jdk9 64位下载官方正式版 1.9 - 系统天堂
  15. jsp语法 --模板元素,表达式,脚本片段,声明,注释
  16. 一个操作共享内存的类!可以方面的添加,删除数据,包括各种结构体!
  17. 库存管理软件挑选窍门:怎么才算合格的库存管理软件?
  18. 网易邮箱已经变成无限空间了
  19. 【python】函数和模块
  20. Altium Designer 18中的System–Design Insight

热门文章

  1. css锯齿边框圆点,CSS实现OSX风格的三个圆点
  2. 现况调查的方法及种类
  3. 修改注册表,关闭window系统自动更新服务
  4. 酒吧里经典的英文歌曲专集(4CD)
  5. 集体涨价出现多米诺骨牌效应?
  6. python 多维数组去重_python多维数组运算-女性时尚流行美容健康娱乐mv-ida网
  7. java毕设项目健身房管理系统设计(附源码)
  8. 骨传导耳机有辐射吗?骨传导耳机到底好不好用?
  9. 数据加速器 GooseFS 1.2.0 版本正式发布
  10. Chrome 自动填充的表单是淡黄色的背景解决办法,