使用StopWatch计算耗时[通俗易懂]

使用StopWatch计算耗时[通俗易懂]一、传统计算耗时方式一般采用System.currentTimeMillis()来获取时间,然后打印当前时间与任务开始执行时间的差值。记录开始时间点记录结束时间点输出当前时间与任务开始执行时间的差值代码如下:publicstaticvoidmain(String[]args)throwsInterruptedException{longstartTime=System.currentTimeMillis();//dos

大家好,又见面了,我是你们的朋友全栈君。

一、传统计算耗时方式

一般采用 System.currentTimeMillis() 来获取时间,然后打印当前时间与任务开始执行时间的差值。

  • 记录开始时间点
  • 记录结束时间点
  • 输出当前时间与任务开始执行时间的差值

代码如下:

    public static void main(String[] args) throws InterruptedException { 
   
        long startTime = System.currentTimeMillis();

        // do something
        TimeUnit.SECONDS.sleep(5);

        System.out.println("执行耗时:" + (System.currentTimeMillis() - startTime) + "ms");
    }

二、使用 Spring 计时器 StopWatch

StopWatch是位于 org.springframework.util包下的一个工具类,通过它可方便的对程序部分代码进行计时(ns级别),可以很方便的计算出任务的耗时.
commons工具包下也有的实现可以直接使用 (org.apache.commons.lang3.time.StopWatch) ,功能差不多。

1、StopWatch使用

通过创建 StopWatch对象,然后调用它的start、stop方法来区分执行任务区间,基于 System.nanoTime()获得时间。 通过 getTotalTimeMillis()方法获得总耗时。

StopWatch的其他方法:

  • prettyPrint()方法,可以优雅的打印出统计分析信息;
  • getTotalTimeMillis()方法,打印出总耗时;
  • getLastTaskName()方法,打印最后一个任务名称;
  • getLastTaskInfo()方法,获得最后一个任务的TaskInfo,进而获得更多相关信息;
  • getTaskCount()方法,获得任务数;

demo1:单业务模块使用

    public static void main(String[] args) throws InterruptedException { 
   
        StopWatch sw = new StopWatch("xx任务的耗时");

        sw.start();
        // do something
        TimeUnit.SECONDS.sleep(5);
        sw.stop();

        System.out.println(sw.getId() + ":"  + sw.getTotalTimeMillis() + "ms");
        System.out.println(sw.getLastTaskName());
        System.out.println(sw.getLastTaskInfo());
        System.out.println(sw.getTaskCount());
        System.out.println(sw.prettyPrint());
    }

在这里插入图片描述

demo2:多业务模块使用

    public static void main(String[] args) throws InterruptedException { 
   
        StopWatch sw = new StopWatch("xx任务的耗时");
        
        sw.start("业务1");
        TimeUnit.SECONDS.sleep(2);
        sw.stop();

        sw.start("业务2");
        TimeUnit.SECONDS.sleep(5);
        sw.stop();

        sw.start("业务3");
        TimeUnit.SECONDS.sleep(3);
        sw.stop();

        System.out.println(sw.getId() + ":"  + sw.getTotalTimeMillis() + "ms");
        System.out.println(sw.prettyPrint());
    }

在这里插入图片描述

StopWatch优缺点:
优点:

  • Spring自带工具类,可直接使用,代码实现简单,使用更简单
    通过多组start、stop方法,将业务代码块进行区分,可获得不同代码块的执行耗时
    统一归纳,展示每项任务耗时与占用总时间的百分比,展示结果直观。
  • 性能消耗相对较小,并且最大程度的保证了start与stop之间的时间记录的准确性

缺点:

  • 一个StopWatch实例一次只能开启一个task,start和stop要成对使用。若要一次开启多个
    task,需要new不同的StopWatch实例
  • 代码侵入式使用,需要改动多处代码

2、Spring中StopWatch源码

该工具类中源码实现也极其简单,通过 start与stop方法分别记录开始时间与结束时间,其中在记录结束时间时,会维护一个链表类型的 tasklist属性,从而使该类可记录多个任务,最后的输出也仅仅是对之前记录的信息做了一个统一的归纳输出,从而使结果更加直观的展示出来。

  • StopWatch也封装了一个记录任务名、结束时间操作的 TaskInfo内部类
  • 在 start方法中记录了任务名称和任务执行的时间,基于 System.nanoTime()获得时间。
  • 在 stop方法中,通过两个时间戳相减获得 lastTime,也就是一个任务的执行时间;lastTime累计相加获得总的执行时间;同时记录任务列表、任务数统计。

StopWatch源码如下:

package org.springframework.util;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.springframework.lang.Nullable;
public class StopWatch { 

private final String id;
private boolean keepTaskList;
private final List<StopWatch.TaskInfo> taskList;
private long startTimeNanos;
@Nullable
private String currentTaskName;
@Nullable
private StopWatch.TaskInfo lastTaskInfo;
private int taskCount;
private long totalTimeNanos;
public StopWatch() { 

this("");
}
public StopWatch(String id) { 

this.keepTaskList = true;
this.taskList = new ArrayList(1);
this.id = id;
}
public String getId() { 

return this.id;
}
public void setKeepTaskList(boolean keepTaskList) { 

this.keepTaskList = keepTaskList;
}
public void start() throws IllegalStateException { 

this.start("");
}
public void start(String taskName) throws IllegalStateException { 

if (this.currentTaskName != null) { 

throw new IllegalStateException("Can't start StopWatch: it's already running");
} else { 

this.currentTaskName = taskName;
this.startTimeNanos = System.nanoTime();
}
}
public void stop() throws IllegalStateException { 

if (this.currentTaskName == null) { 

throw new IllegalStateException("Can't stop StopWatch: it's not running");
} else { 

long lastTime = System.nanoTime() - this.startTimeNanos;
this.totalTimeNanos += lastTime;
this.lastTaskInfo = new StopWatch.TaskInfo(this.currentTaskName, lastTime);
if (this.keepTaskList) { 

this.taskList.add(this.lastTaskInfo);
}
++this.taskCount;
this.currentTaskName = null;
}
}
public boolean isRunning() { 

return this.currentTaskName != null;
}
@Nullable
public String currentTaskName() { 

return this.currentTaskName;
}
public long getLastTaskTimeNanos() throws IllegalStateException { 

if (this.lastTaskInfo == null) { 

throw new IllegalStateException("No tasks run: can't get last task interval");
} else { 

return this.lastTaskInfo.getTimeNanos();
}
}
public long getLastTaskTimeMillis() throws IllegalStateException { 

if (this.lastTaskInfo == null) { 

throw new IllegalStateException("No tasks run: can't get last task interval");
} else { 

return this.lastTaskInfo.getTimeMillis();
}
}
public String getLastTaskName() throws IllegalStateException { 

if (this.lastTaskInfo == null) { 

throw new IllegalStateException("No tasks run: can't get last task name");
} else { 

return this.lastTaskInfo.getTaskName();
}
}
public StopWatch.TaskInfo getLastTaskInfo() throws IllegalStateException { 

if (this.lastTaskInfo == null) { 

throw new IllegalStateException("No tasks run: can't get last task info");
} else { 

return this.lastTaskInfo;
}
}
public long getTotalTimeNanos() { 

return this.totalTimeNanos;
}
public long getTotalTimeMillis() { 

return nanosToMillis(this.totalTimeNanos);
}
public double getTotalTimeSeconds() { 

return nanosToSeconds(this.totalTimeNanos);
}
public int getTaskCount() { 

return this.taskCount;
}
public StopWatch.TaskInfo[] getTaskInfo() { 

if (!this.keepTaskList) { 

throw new UnsupportedOperationException("Task info is not being kept!");
} else { 

return (StopWatch.TaskInfo[])this.taskList.toArray(new StopWatch.TaskInfo[0]);
}
}
public String shortSummary() { 

return "StopWatch '" + this.getId() + "': running time = " + this.getTotalTimeNanos() + " ns";
}
public String prettyPrint() { 

StringBuilder sb = new StringBuilder(this.shortSummary());
sb.append('\n');
if (!this.keepTaskList) { 

sb.append("No task info kept");
} else { 

sb.append("---------------------------------------------\n");
sb.append("ns % Task name\n");
sb.append("---------------------------------------------\n");
NumberFormat nf = NumberFormat.getNumberInstance();
nf.setMinimumIntegerDigits(9);
nf.setGroupingUsed(false);
NumberFormat pf = NumberFormat.getPercentInstance();
pf.setMinimumIntegerDigits(3);
pf.setGroupingUsed(false);
StopWatch.TaskInfo[] var4 = this.getTaskInfo();
int var5 = var4.length;
for(int var6 = 0; var6 < var5; ++var6) { 

StopWatch.TaskInfo task = var4[var6];
sb.append(nf.format(task.getTimeNanos())).append(" ");
sb.append(pf.format((double)task.getTimeNanos() / (double)this.getTotalTimeNanos())).append(" ");
sb.append(task.getTaskName()).append("\n");
}
}
return sb.toString();
}
public String toString() { 

StringBuilder sb = new StringBuilder(this.shortSummary());
if (this.keepTaskList) { 

StopWatch.TaskInfo[] var2 = this.getTaskInfo();
int var3 = var2.length;
for(int var4 = 0; var4 < var3; ++var4) { 

StopWatch.TaskInfo task = var2[var4];
sb.append("; [").append(task.getTaskName()).append("] took ").append(task.getTimeNanos()).append(" ns");
long percent = Math.round(100.0D * (double)task.getTimeNanos() / (double)this.getTotalTimeNanos());
sb.append(" = ").append(percent).append("%");
}
} else { 

sb.append("; no task info kept");
}
return sb.toString();
}
private static long nanosToMillis(long duration) { 

return TimeUnit.NANOSECONDS.toMillis(duration);
}
private static double nanosToSeconds(long duration) { 

return (double)duration / 1.0E9D;
}
public static final class TaskInfo { 

private final String taskName;
private final long timeNanos;
TaskInfo(String taskName, long timeNanos) { 

this.taskName = taskName;
this.timeNanos = timeNanos;
}
public String getTaskName() { 

return this.taskName;
}
public long getTimeNanos() { 

return this.timeNanos;
}
public long getTimeMillis() { 

return StopWatch.nanosToMillis(this.timeNanos);
}
public double getTimeSeconds() { 

return StopWatch.nanosToSeconds(this.timeNanos);
}
}
}

– 求知若饥,虚心若愚。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/152459.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 深入了解Flutter的isolate(1) —- 事件循环(event loop)及代码运行顺序

    深入了解Flutter的isolate(1) —- 事件循环(event loop)及代码运行顺序

  • 怎么获取枚举的值_枚举是值类型吗

    怎么获取枚举的值_枚举是值类型吗最近在做一个学校的系统,其中用到一些枚举,可是在显示下拉列表时要绑定枚举的描述及其枚举值时就只一个一个的默认设死,这样不灵活。有没有其快捷方法?搜了下百度很多相关资料有了些许眉目,代码如下1.首先定

  • java二维数组试题_Java二维数组及习题总结

    java二维数组试题_Java二维数组及习题总结二维数组二维数组:就是一个由行和列组成的一个矩阵(Matrix);在这个矩阵中访问元素时,是根据元素的行角标和列角标所确定的。二维数组在内存中的存储:无论是二维数组,还是多维数组,它们本身就是一个一维数组,只不过该一维数组中的每一个元素是另一个一维数组。二维数组的创建:int[][]matrix=newint[3][4]———创建一个3行4列的二维数组,元素默认都是0;int[]…

  • 2018阿里巴巴春季校招笔试题(Java开发)「建议收藏」

    2018阿里巴巴春季校招笔试题(Java开发)「建议收藏」第一题:编程题要求:编译器版本:Java1.8.0_66请使用标准输入输出(System.in,System.out);已禁用图形、文件、网络、系统相关的操作,如java.lang.Process,javax.swing.JFrame,Runtime.getRuntime;不要自定义包名称,否则会报错,即不要添加packageanswer之类的语句;您可以写很多个类,但是必须有一个…

  • idea2019.2激活码【中文破解版】

    (idea2019.2激活码)最近有小伙伴私信我,问我这边有没有免费的intellijIdea的激活码,然后我将全栈君台教程分享给他了。激活成功之后他一直表示感谢,哈哈~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.cn/100143.html…

  • LoadRunner基础入门教程

    LoadRunner基础入门教程方法/步骤   1:LoadRunner是一款性能测试软件,通过模拟真实的用户行为,通过负载、并发和性能实时监控以及完成后的测试报告,分析系统可能存在的瓶颈,LoadRunner最为有效的手段之一应该就是并发的控制。通过在控制台的设置,以达到同一个业务同时模拟成千上万的用户进行操作。  2:安装完成LoadRunner后,进入初始化界面。先对初始化界面做一个简单介绍:在界面左侧有三项分别为:…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号