StopWatch的使用

Posted 初夏0811

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了StopWatch的使用相关的知识,希望对你有一定的参考价值。

一、简介

stopWatch是org.springframework.util包下的一个工具类,使用它可直观的输出代码执行耗时,以及执行时间百分比,瞬间感觉比之前的方式高大上了一个档次。

在未使用这个工具类之前,如果我们需要统计某段代码的耗时,我们会这样写:

public static void main(String[] args) throws InterruptedException 
        test0();
    

    public static void test0() throws InterruptedException 
        long start = System.currentTimeMillis();
        // do something
        Thread.sleep(100);
        long end = System.currentTimeMillis();
        long start2 = System.currentTimeMillis();
        // do something
        Thread.sleep(200);
        long end2 = System.currentTimeMillis();
        System.out.println("某某1执行耗时:" + (end - start));
        System.out.println("某某2执行耗时:" + (end2 - start2));
    

执行结果如下:

某某1执行耗时:100
某某2执行耗时:200

可以看出我们的代码比较繁琐,如果要统计更多的任务计时呢?更繁琐,甚至让代码显得有点low
下面来看一个stopWatch实现的一个示例:

public class StopWatchDemo 
    public static void main(String[] args) throws InterruptedException 
        test1();
    

    public static void test1() throws InterruptedException 
        StopWatch sw = new StopWatch("test");
        sw.start("task1");
        // do something
        Thread.sleep(100);
        sw.stop();
        sw.start("task2");
        // do something
        Thread.sleep(200);
        sw.stop();
        System.out.println("sw.prettyPrint()~~~~~~~~~~~~~~~~~");
        System.out.println(sw.prettyPrint());
    


运行结果如下:

sw.prettyPrint()~~~~~~~~~~~~~~~~~
StopWatch 'test': running time (millis) = 310
-----------------------------------------
ms     %     Task name
-----------------------------------------
00110  035%  task1
00200  065%  task2

瞬间代码简介了,也高大上了,除此之外,还有以下两个方法shortSummary,getTotalTimeMillis,查看程序执行时间。

System.out.println("sw.shortSummary()~~~~~~~~~~~~~~~~~");
System.out.println(sw.shortSummary());
System.out.println("sw.getTotalTimeMillis()~~~~~~~~~~~~~~~~~");
System.out.println(sw.getTotalTimeMillis());
运行结果
sw.shortSummary()~~~~~~~~~~~~~~~~~
StopWatch 'test': running time (millis) = 308
sw.getTotalTimeMillis()~~~~~~~~~~~~~~~~~
308

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

import java.text.NumberFormat;
import java.util.LinkedList;
import java.util.List;

public class StopWatch 
    private final String id;
    private boolean keepTaskList = true;
    private final List<TaskInfo> taskList = new LinkedList();
    private long startTimeMillis;
    private boolean running;
    private String currentTaskName;
    private StopWatch.TaskInfo lastTaskInfo;
    private int taskCount;
    private long totalTimeMillis;

    public StopWatch() 
        this.id = "";
    

    public StopWatch(String id) 
        this.id = 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.running) 
            throw new IllegalStateException("Can't start StopWatch: it's already running");
         else 
            this.startTimeMillis = System.currentTimeMillis();
            this.running = true;
            this.currentTaskName = taskName;
        
    

    public void stop() throws IllegalStateException 
        if (!this.running) 
            throw new IllegalStateException("Can't stop StopWatch: it's not running");
         else 
            long lastTime = System.currentTimeMillis() - this.startTimeMillis;
            this.totalTimeMillis += lastTime;
            this.lastTaskInfo = new StopWatch.TaskInfo(this.currentTaskName, lastTime);
            if (this.keepTaskList) 
                this.taskList.add(this.lastTaskInfo);
            

            ++this.taskCount;
            this.running = false;
            this.currentTaskName = null;
        
    

    public boolean isRunning() 
        return this.running;
    

    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 getTotalTimeMillis() 
        return this.totalTimeMillis;
    

    public double getTotalTimeSeconds() 
        return (double) this.totalTimeMillis / 1000.0D;
    

    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[this.taskList.size()]);
        
    

    public String shortSummary() 
        return "StopWatch '" + this.id + "': running time (millis) = " + this.getTotalTimeMillis();
    

    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("ms     %     Task name\\n");
            sb.append("-----------------------------------------\\n");
            NumberFormat nf = NumberFormat.getNumberInstance();
            nf.setMinimumIntegerDigits(5);
            nf.setGroupingUsed(false);
            NumberFormat pf = NumberFormat.getPercentInstance();
            pf.setMinimumIntegerDigits(3);
            pf.setGroupingUsed(false);
            StopWatch.TaskInfo[] var7;
            int var6 = (var7 = this.getTaskInfo()).length;

            for (int var5 = 0; var5 < var6; ++var5) 
                StopWatch.TaskInfo task = var7[var5];
                sb.append(nf.format(task.getTimeMillis())).append("  ");
                sb.append(pf.format(task.getTimeSeconds() / this.getTotalTimeSeconds())).append("  ");
                sb.append(task.getTaskName()).append("\\n");
            
        

        return sb.toString();
    

    @Override
    public String toString() 
        StringBuilder sb = new StringBuilder(this.shortSummary());
        if (this.keepTaskList) 
            StopWatch.TaskInfo[] var5;
            int var4 = (var5 = this.getTaskInfo()).length;

            for (int var3 = 0; var3 < var4; ++var3) 
                StopWatch.TaskInfo task = var5[var3];
                sb.append("; [").append(task.getTaskName()).append("] took ").append(task.getTimeMillis());
                long percent = Math.round(100.0D * task.getTimeSeconds() / this.getTotalTimeSeconds());
                sb.append(" = ").append(percent).append("%");
            
         else 
            sb.append("; no task info kept");
        

        return sb.toString();
    

    public static final class TaskInfo 
        private final String taskName;
        private final long timeMillis;

        TaskInfo(String taskName, long timeMillis) 
            this.taskName = taskName;
            this.timeMillis = timeMillis;
        

        public String getTaskName() 
            return this.taskName;
        

        public long getTimeMillis() 
            return this.timeMillis;
        

        public double getTimeSeconds() 
            return (double) this.timeMillis / 1000.0D;
        
    



看源码就知道为何会打印如上那么高大上了。

最后来说下StopWatch优缺点:
优点
1.spring自带工具类,可直接使用;
2.代码实现简单,使用更简单;
3.统一归纳,展示每项任务耗时与占用总时间的百分比,展示结果直观,性能消耗相对较小,并且最大程度的保证了start与stop之间的时间记录的准确性;
4.可在start时直接指定任务名字,从而更加直观的显示记录结果。

缺点:
1.一个StopWatch实例一次只能开启一个task,不能同时start多个task,并且在该task未stop之前不能,start一个新的task,必须在该task stop之后才能开启新的task,若要一次开启多个,需要new不同的StopWatch实例;
3.代码侵入式使用,需要改动多处代码。

C# StopWatch的使用

  在做项目的时候,需要输出数据库操作的耗时,自己写了个方法。老大看到后,奇怪我为什么不用现成的。才知道有StopWatch这个类。

属性
 
 
 名称说明
技术分享 Elapsed

获取当前实例测量得出的总运行时间。

技术分享 ElapsedMilliseconds

获取当前实例测量得出的总运行时间(以毫秒为单位)。

技术分享 ElapsedTicks

获取当前实例测量得出的总运行时间(用计时器刻度表示)。

技术分享 IsRunning

获取一个值,该值表示 Stopwatch 计时器是否正在运行。

方法
 
 
 名称说明
技术分享 Equals(Object)

确定指定的对象是否等于当前对象。(继承自 Object。)

技术分享 Finalize()

在垃圾回收将某一对象回收前允许该对象尝试释放资源并执行其他清理操作。(继承自 Object。)

技术分享 GetHashCode()

作为默认哈希函数。(继承自 Object。)

技术分享技术分享 GetTimestamp()

获取计时器机制中的当前刻度数。

技术分享 GetType()

获取当前实例的 Type。(继承自 Object。)

技术分享 MemberwiseClone()

创建当前 Object 的浅表副本。(继承自 Object。)

技术分享 Reset()

停止时间间隔测量,并将运行时间重置为零。

技术分享 Restart()

停止时间间隔测量,将运行时间重置为零,然后开始测量运行时间。

技术分享 Start()

开始或继续测量某个时间间隔的运行时间。

技术分享技术分享 StartNew()

初始化新的 Stopwatch 实例,将运行时间属性设置为零,然后开始测量运行时间。

技术分享 Stop()

停止测量某个时间间隔的运行时间。

技术分享 ToString()

返回表示当前对象的字符串。(继承自 Object。)

以上是关于StopWatch的使用的主要内容,如果未能解决你的问题,请参考以下文章

C# StopWatch的使用

spring StopWatch用法

spring StopWatch用法

别再用 System.currentTimeMillis() 统计耗时了,太 Low,StopWatch 好用到爆!

c#程序stopwatch怎么使用

C#记录程序耗时方法