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

    文章

    2957

    浏览量

    104539
  • 代码
    +关注

    关注

    30

    文章

    4742

    浏览量

    68333
  • spring
    +关注

    关注

    0

    文章

    338

    浏览量

    14307
  • Apache
    +关注

    关注

    0

    文章

    64

    浏览量

    12448

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

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

收藏 人收藏

    评论

    相关推荐

    如何缩短Vivado的运行时间

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

    如何检查Linux服务器的运行时间

    Linux 中的 uptime 用于查看系统启动后的运行时间。它是一个比较简单的 Linux 命令,可以不带参数直接运行
    发表于 11-25 15:25 1.5w次阅读
    如何检查Linux服务器的<b class='flag-5'>运行时间</b>

    stm32cubeIDE代码运行时间如何查看?

    stm32cubeIDE 代码运行时间,如何查看?就如 keil 调试时候那样,可以测试代码运行时间。但是在stm32cubeIDE 中,一直没有找到这个功能,不知道哪位高人可以提示
    发表于 04-16 08:10

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

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

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

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

    如何用SysTick实现测量程序运行时间

    在实际的项目开发过程中,常常遇到需要得到一段代码运行时间,通常的方法是用示波器来测量,这篇博文将用 SysTick 来实现 精确测量 程序运行时间。 STM32F4 的内核定时
    的头像 发表于 05-09 14:07 6006次阅读
    如何用SysTick实现测量程序<b class='flag-5'>运行时间</b>

    KEIL的代码运行时间功能

    郭老师说,这个时间单位是秒(sec),是从单片机运行第一条代码开始计算的,但是当你真正用示波器验证这个时间差(因为不知道单片机什么时候才开始运行
    的头像 发表于 06-05 15:48 8702次阅读
    KEIL的<b class='flag-5'>代码</b><b class='flag-5'>运行时间</b>功能

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

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

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

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

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

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

    ch32v307记录程序运行时间

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

    如何保证它们容器运行时的安全?

    紧密耦合的容器运行时继承了主机操作系统的安全态势和攻击面。运行时或主机内核中的任何漏洞及其利用都会成为攻击者的潜在切入点。
    的头像 发表于 11-03 15:24 635次阅读

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

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

    jvm运行时内存区域划分

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

    三菱plc累计运行时间怎么编程

    具有重要意义。本文将详细介绍如何使用三菱PLC编程实现累计运行时间的统计功能。 一、概述 累计运行时间是指设备或系统在一定时间内的总运行时间。在工业生产中,对设备的累计
    的头像 发表于 06-20 11:31 2111次阅读