0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

利用StopWatch监控Java代码运行时间和分析性能

Android编程精选 来源:CSDN技术社区 作者:独泪了无痕 2022-07-21 16:51 次阅读

利用StopWatch监控Java代码运行时间和分析性能

一、背景

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

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 都已经自动引入了该包:

    org.springframework    spring-core    ${spring.version}

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

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 taskList;    /**  * 当前任务的开始时间  */    private long startTimeMillis;    /**  *   */    private boolean running;    /**  * 当前任务名称  */    private String currentTaskName;    /**  * 最后一个任务的信息  */    private StopWatch.TaskInfo lastTaskInfo;    /**  * 任务总数  */    private int taskCount;    /**  * 程序执行时间  */    private long totalTimeMillis;    ...}

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

089914ba-0758-11ed-ba43-dac502259ad0.png

2.3 注意事项

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

三、apache 用法

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

08a97ee0-0758-11ed-ba43-dac502259ad0.png

    org.apache.commons    commons-lang3    3.6

		
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");}

四、最后

很多时候,写代码也是一种艺术,而借助这种实用工具我就觉得艺术感更强些。希望我们能有追求更加美好事物的心,这点对于接纳新知识特别重要。

此处推荐这个监视器来代替之前的的使用,能让小伙伴们更加灵活的分析你的代码。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • JAVA
    +关注

    关注

    19

    文章

    2903

    浏览量

    102875
  • 代码
    +关注

    关注

    30

    文章

    4536

    浏览量

    66501
  • spring
    +关注

    关注

    0

    文章

    332

    浏览量

    14143
  • Apache
    +关注

    关注

    0

    文章

    63

    浏览量

    12286

原文标题:求求你别再用 System.currentTimeMillis() 统计代码耗时了,真的太 Low 了!

文章出处:【微信号:AndroidPush,微信公众号:Android编程精选】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    如何缩短Vivado的运行时间

    在Vivado Implementation阶段,有时是有必要分析一下什么原因导致运行时间(runtime)过长,从而找到一些方法来缩短运行时间
    的头像 发表于 05-29 14:37 1.4w次阅读
    如何缩短Vivado的<b class='flag-5'>运行时间</b>

    freertos的任务运行时间怎么设置

    对于相同优先级的任务采用时间片轮询的方式运行,那比如说有两个优先级都为5的任务,那这两个任务的运行时间如何设置呢?在rt-thread中创建任务时就可以设置任务的运行时间,在freer
    发表于 07-19 08:03

    请问6747如何测量代码运行时间

    1. 我想用片上的硬件定时器的方法测量代码运行时间,使用timer,加头文件:csl_timer.h,但是6747没有csl,我下载了6747的cslr package,发现里面也没有
    发表于 07-28 10:25

    C语言教程之显示程序运行时间

    C语言教程之显示程序运行时间,很好的C语言资料,快来学习吧。
    发表于 04-25 16:09 0次下载

    电机运行时间进行排列 是分为两个部分来完成这个程序的设计的

    前几天有个学员咨询一个程序设计的问题,程序的控制要求如下:需要控制5台电机的运行,每台电机运行时需要记录运行时间,电机启动运行时,根据记录的运行时间
    的头像 发表于 07-19 08:57 6424次阅读
    电机<b class='flag-5'>运行时间</b>进行排列 是分为两个部分来完成这个程序的设计的

    如何高效测量ECU的运行时间

    ,最终可能会引起运行时间方面的问题。这在项目后期需要大量的时间和金钱来解决。如果不能掌握系统的运行状态,则很难发现系统内缺陷的根源。 解决方案 将TA软件工具套件与VX1000测量标定硬件相结合,可同步
    的头像 发表于 10-28 11:05 1818次阅读

    浅析STM32代码运行时间的技巧

    前言     测试代码运行时间的两种方法: 使用单片机内部定时器,在待测程序段的开始启动定时器,在待测程序段的结尾关闭定时器。为了测量的准确性,要进行多次测量,并进行平均取值。 借助示波器的方法
    的头像 发表于 11-09 09:52 3332次阅读
    浅析STM32<b class='flag-5'>代码</b><b class='flag-5'>运行时间</b>的技巧

    下一代电池监控器:如何在提高精度和延长运行时间的同时提高电池的安全性

    下一代电池监控器:如何在提高精度和延长运行时间的同时提高电池的安全性
    发表于 10-31 08:23 0次下载
    下一代电池<b class='flag-5'>监控</b>器:如何在提高精度和延长<b class='flag-5'>运行时间</b>的同时提高电池的安全性

    了解如何让您的汽车电池更稳定、运行时间更长

    了解如何让您的汽车电池更稳定、运行时间更长
    发表于 11-01 08:27 0次下载
    了解如何让您的汽车电池更稳定、<b class='flag-5'>运行时间</b>更长

    Go运行时:4年之后

    自 2018 年以来,Go GC,以及更广泛的 Go 运行时,一直在稳步改进。近日,Go 社区总结了 4 年来 Go 运行时的一些重要变化。
    的头像 发表于 11-30 16:21 502次阅读

    AN021 测量MCU代码运行时间的几种方法

    AN021 测量MCU代码运行时间的几种方法
    发表于 02-27 18:23 0次下载
    AN021 测量MCU<b class='flag-5'>代码</b><b class='flag-5'>运行时间</b>的几种方法

    优化HBM2E运行时性能

    性能仍然是任何复杂片上系统 (SoC) 设计的关键因素。此外,复杂性每天都在增加,这给工程师跟踪设计性能带来了挑战,但他们的任务是不断提高芯片性能。在运行时
    的头像 发表于 05-26 10:17 385次阅读
    优化HBM2E<b class='flag-5'>运行时</b><b class='flag-5'>性能</b>

    ch32v307记录程序运行时间

    ,不仅会降低用户的体验,甚至可能会导致系统的崩溃。 因此,在程序设计和调试中,我们常常需要记录程序的运行时间,并通过不断的优化来提升程序的性能。本文将介绍如何在各种编程语言中记录程序运行时间,并分享一些提高程序
    的头像 发表于 08-22 15:53 426次阅读

    如何在 CFD 设计中利用网格维护几何形状并减少运行时间

    如何在 CFD 设计中利用网格维护几何形状并减少运行时间
    的头像 发表于 11-24 17:07 188次阅读
    如何在 CFD 设计中<b class='flag-5'>利用</b>网格维护几何形状并减少<b class='flag-5'>运行时间</b>?

    jvm运行时内存区域划分

    JVM是Java Virtual Machine(Java虚拟机)的缩写,它是Java编程语言的运行环境。JVM的主要功能是将Java
    的头像 发表于 12-05 14:08 221次阅读