StopWatch是位于org.springframework.util包下的一个工具类,通过它可方便的对程序部分代码进行计时(ms级别),适用于同步单线程代码块。
正常情况下,我们如果需要看某段代码的执行耗时,会通过如下的方式进行查看:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public static void main(String[] args) throws InterruptedException { StopWatchTest.test0(); // StopWatchTest.test1(); }
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 2 3 |
运行结果: 某某1执行耗时:105 某某2执行耗时:203 |
该种方法通过获取执行完成时间与执行开始时间的差值得到程序的执行时间,简单直接有效,但想必写多了也是比较烦人的,尤其是碰到不可描述的代码时,会更加的让人忍不住多写几个bug聊表敬意,而且该结果也不够直观,此时会想是否有一个工具类,提供了这些方法,或者自己写个工具类,刚好可以满足这种场景,并且把结果更加直观的展现出来。
首先我们的需求如下:
根据该需求,我们可直接使用org.springframework.util包下的一个工具类StopWatch,通过该工具类,我们对上述代码做如下改造:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public static void main(String[] args) throws InterruptedException { // StopWatchTest.test0(); StopWatchTest.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()); } |
1 2 3 4 5 6 7 8 |
运行结果: sw.prettyPrint()~~~~~~~~~~~~~~~~~ StopWatch 'test': running time (millis) = 308 ----------------------------------------- ms % Task name ----------------------------------------- 00104 034% task1 00204 066% task2 |
start开始记录,stop停止记录,然后通过StopWatch的prettyPrint方法,可直观的输出代码执行耗时,以及执行时间百分比,瞬间感觉比之前的方式高大上了一个档次。
除此之外,还有以下两个方法shortSummary,getTotalTimeMillis,查看程序执行时间。
运行代码及结果:
1 2 3 4 5 6 7 8 9 |
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属性,从而使该类可记录多个任务,最后的输出也仅仅是对之前记录的信息做了一个统一的归纳输出,从而使结果更加直观的展示出来。
StopWatch优缺点:
优点:
缺点:
一个StopWatch实例一次只能开启一个task,不能同时start多个task,并且在该task未stop之前不能start一个新的task,必须在该task stop之后才能开启新的task,若要一次开启多个,需要new不同的StopWatch实例 代码侵入式使用,需要改动多处代码spring中StopWatch源码实现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
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; } }
} |
到此这篇关于Spring计时器stopwatch使用详解的文章就介绍到这了,更多相关Spring计时器stopwatch内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
原文链接:https://blog.csdn.net/gxs1688/article/details/87185030
查看更多关于Spring计时器stopwatch使用详解的详细内容...