Spring—spring提供的一个简单的任务执行时间监视器 StopWatch

时间:2021-02-18 18:15:24

有时我们在做开发的时候需要记录每个任务执行时间,或者记录一段代码执行时间,最简单的方法就是打印当前时间与执行完时间的差值,然后这样如果执行大量测试的话就很麻烦,并且不直观,如果想对执行的时间做进一步控制,则需要在程序中很多地方修改,目前spring-framework提供了一个StopWatch类可以做类似任务执行时间控制,也就是封装了一个对开始时间,结束时间记录操作的java类,当然还有一些其他控制,代码如下:

[java] view plain copy
  1. /* 
  2.  * Copyright 2002-2010 the original author or authors. 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *      http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  */  
  16.   
  17. package com.test;  
  18.   
  19. import java.text.NumberFormat;  
  20. import java.util.LinkedList;  
  21. import java.util.List;  
  22.   
  23. /** 
  24.  * Simple stop watch, allowing for timing of a number of tasks, 
  25.  * exposing total running time and running time for each named task. 
  26.  * 
  27.  * <p>Conceals use of <code>System.currentTimeMillis()</code>, improving the 
  28.  * readability of application code and reducing the likelihood of calculation errors. 
  29.  * 
  30.  * <p>Note that this object is not designed to be thread-safe and does not 
  31.  * use synchronization. 
  32.  * 
  33.  * <p>This class is normally used to verify performance during proof-of-concepts 
  34.  * and in development, rather than as part of production applications. 
  35.  * 
  36.  * @author Rod Johnson 
  37.  * @author Juergen Hoeller 
  38.  * @author Sam Brannen 
  39.  * @since May 2, 2001 
  40.  */  
  41. public class StopWatch {  
  42.   
  43.     /** 
  44.      * Identifier of this stop watch. 
  45.      * Handy when we have output from multiple stop watches 
  46.      * and need to distinguish between them in log or console output. 
  47.      */  
  48.     private final String id;  
  49.   
  50.     private boolean keepTaskList = true;  
  51.   
  52.     private final List<TaskInfo> taskList = new LinkedList<TaskInfo>();  
  53.   
  54.     /** Start time of the current task */  
  55.     private long startTimeMillis;  
  56.   
  57.     /** Is the stop watch currently running? */  
  58.     private boolean running;  
  59.   
  60.     /** Name of the current task */  
  61.     private String currentTaskName;  
  62.   
  63.     private TaskInfo lastTaskInfo;  
  64.   
  65.     private int taskCount;  
  66.   
  67.     /** Total running time */  
  68.     private long totalTimeMillis;  
  69.   
  70.   
  71.     /** 
  72.      * Construct a new stop watch. Does not start any task. 
  73.      */  
  74.     public StopWatch() {  
  75.         this.id = "";  
  76.     }  
  77.   
  78.     /** 
  79.      * Construct a new stop watch with the given id. 
  80.      * Does not start any task. 
  81.      * @param id identifier for this stop watch. 
  82.      * Handy when we have output from multiple stop watches 
  83.      * and need to distinguish between them. 
  84.      */  
  85.     public StopWatch(String id) {  
  86.         this.id = id;  
  87.     }  
  88.   
  89.   
  90.     /** 
  91.      * Determine whether the TaskInfo array is built over time. Set this to 
  92.      * "false" when using a StopWatch for millions of intervals, or the task 
  93.      * info structure will consume excessive memory. Default is "true". 
  94.      */  
  95.     public void setKeepTaskList(boolean keepTaskList) {  
  96.         this.keepTaskList = keepTaskList;  
  97.     }  
  98.   
  99.   
  100.     /** 
  101.      * Start an unnamed task. The results are undefined if {@link #stop()} 
  102.      * or timing methods are called without invoking this method. 
  103.      * @see #stop() 
  104.      */  
  105.     public void start() throws IllegalStateException {  
  106.         start("");  
  107.     }  
  108.   
  109.     /** 
  110.      * Start a named task. The results are undefined if {@link #stop()} 
  111.      * or timing methods are called without invoking this method. 
  112.      * @param taskName the name of the task to start 
  113.      * @see #stop() 
  114.      */  
  115.     public void start(String taskName) throws IllegalStateException {  
  116.         if (this.running) {  
  117.             throw new IllegalStateException("Can't start StopWatch: it's already running");  
  118.         }  
  119.         this.startTimeMillis = System.currentTimeMillis();  
  120.         this.running = true;  
  121.         this.currentTaskName = taskName;  
  122.     }  
  123.   
  124.     /** 
  125.      * Stop the current task. The results are undefined if timing 
  126.      * methods are called without invoking at least one pair 
  127.      * {@link #start()} / {@link #stop()} methods. 
  128.      * @see #start() 
  129.      */  
  130.     public void stop() throws IllegalStateException {  
  131.         if (!this.running) {  
  132.             throw new IllegalStateException("Can't stop StopWatch: it's not running");  
  133.         }  
  134.         long lastTime = System.currentTimeMillis() - this.startTimeMillis;  
  135.         this.totalTimeMillis += lastTime;  
  136.         this.lastTaskInfo = new TaskInfo(this.currentTaskName, lastTime);  
  137.         if (this.keepTaskList) {  
  138.             this.taskList.add(lastTaskInfo);  
  139.         }  
  140.         ++this.taskCount;  
  141.         this.running = false;  
  142.         this.currentTaskName = null;  
  143.     }  
  144.   
  145.     /** 
  146.      * Return whether the stop watch is currently running. 
  147.      */  
  148.     public boolean isRunning() {  
  149.         return this.running;  
  150.     }  
  151.   
  152.   
  153.     /** 
  154.      * Return the time taken by the last task. 
  155.      */  
  156.     public long getLastTaskTimeMillis() throws IllegalStateException {  
  157.         if (this.lastTaskInfo == null) {  
  158.             throw new IllegalStateException("No tasks run: can't get last task interval");  
  159.         }  
  160.         return this.lastTaskInfo.getTimeMillis();  
  161.     }  
  162.   
  163.     /** 
  164.      * Return the name of the last task. 
  165.      */  
  166.     public String getLastTaskName() throws IllegalStateException {  
  167.         if (this.lastTaskInfo == null) {  
  168.             throw new IllegalStateException("No tasks run: can't get last task name");  
  169.         }  
  170.         return this.lastTaskInfo.getTaskName();  
  171.     }  
  172.   
  173.     /** 
  174.      * Return the last task as a TaskInfo object. 
  175.      */  
  176.     public TaskInfo getLastTaskInfo() throws IllegalStateException {  
  177.         if (this.lastTaskInfo == null) {  
  178.             throw new IllegalStateException("No tasks run: can't get last task info");  
  179.         }  
  180.         return this.lastTaskInfo;  
  181.     }  
  182.   
  183.   
  184.     /** 
  185.      * Return the total time in milliseconds for all tasks. 
  186.      */  
  187.     public long getTotalTimeMillis() {  
  188.         return this.totalTimeMillis;  
  189.     }  
  190.   
  191.     /** 
  192.      * Return the total time in seconds for all tasks. 
  193.      */  
  194.     public double getTotalTimeSeconds() {  
  195.         return this.totalTimeMillis / 1000.0;  
  196.     }  
  197.   
  198.     /** 
  199.      * Return the number of tasks timed. 
  200.      */  
  201.     public int getTaskCount() {  
  202.         return this.taskCount;  
  203.     }  
  204.   
  205.     /** 
  206.      * Return an array of the data for tasks performed. 
  207.      */  
  208.     public TaskInfo[] getTaskInfo() {  
  209.         if (!this.keepTaskList) {  
  210.             throw new UnsupportedOperationException("Task info is not being kept!");  
  211.         }  
  212.         return this.taskList.toArray(new TaskInfo[this.taskList.size()]);  
  213.     }  
  214.   
  215.   
  216.     /** 
  217.      * Return a short description of the total running time. 
  218.      */  
  219.     public String shortSummary() {  
  220.         return "StopWatch '" + this.id + "': running time (millis) = " + getTotalTimeMillis();  
  221.     }  
  222.   
  223.     /** 
  224.      * Return a string with a table describing all tasks performed. 
  225.      * For custom reporting, call getTaskInfo() and use the task info directly. 
  226.      */  
  227.     public String prettyPrint() {  
  228.         StringBuilder sb = new StringBuilder(shortSummary());  
  229.         sb.append('\n');  
  230.         if (!this.keepTaskList) {  
  231.             sb.append("No task info kept");  
  232.         } else {  
  233.             sb.append("-----------------------------------------\n");  
  234.             sb.append("ms     %     Task name\n");  
  235.             sb.append("-----------------------------------------\n");  
  236.             NumberFormat nf = NumberFormat.getNumberInstance();  
  237.             nf.setMinimumIntegerDigits(5);  
  238.             nf.setGroupingUsed(false);  
  239.             NumberFormat pf = NumberFormat.getPercentInstance();  
  240.             pf.setMinimumIntegerDigits(3);  
  241.             pf.setGroupingUsed(false);  
  242.             for (TaskInfo task : getTaskInfo()) {  
  243.                 sb.append(nf.format(task.getTimeMillis())).append("  ");  
  244.                 sb.append(pf.format(task.getTimeSeconds() / getTotalTimeSeconds())).append("  ");  
  245.                 sb.append(task.getTaskName()).append("\n");  
  246.             }  
  247.         }  
  248.         return sb.toString();  
  249.     }  
  250.   
  251.     /** 
  252.      * Return an informative string describing all tasks performed 
  253.      * For custom reporting, call <code>getTaskInfo()</code> and use the task info directly. 
  254.      */  
  255.     @Override  
  256.     public String toString() {  
  257.         StringBuilder sb = new StringBuilder(shortSummary());  
  258.         if (this.keepTaskList) {  
  259.             for (TaskInfo task : getTaskInfo()) {  
  260.                 sb.append("; [").append(task.getTaskName()).append("] took ").append(task.getTimeMillis());  
  261.                 long percent = Math.round((100.0 * task.getTimeSeconds()) / getTotalTimeSeconds());  
  262.                 sb.append(" = ").append(percent).append("%");  
  263.             }  
  264.         } else {  
  265.             sb.append("; no task info kept");  
  266.         }  
  267.         return sb.toString();  
  268.     }  
  269.   
  270.   
  271.     /** 
  272.      * Inner class to hold data about one task executed within the stop watch. 
  273.      */  
  274.     public static final class TaskInfo {  
  275.   
  276.         private final String taskName;  
  277.   
  278.         private final long timeMillis;  
  279.   
  280.         TaskInfo(String taskName, long timeMillis) {  
  281.             this.taskName = taskName;  
  282.             this.timeMillis = timeMillis;  
  283.         }  
  284.   
  285.         /** 
  286.          * Return the name of this task. 
  287.          */  
  288.         public String getTaskName() {  
  289.             return this.taskName;  
  290.         }  
  291.   
  292.         /** 
  293.          * Return the time in milliseconds this task took. 
  294.          */  
  295.         public long getTimeMillis() {  
  296.             return this.timeMillis;  
  297.         }  
  298.   
  299.         /** 
  300.          * Return the time in seconds this task took. 
  301.          */  
  302.         public double getTimeSeconds() {  
  303.             return this.timeMillis / 1000.0;  
  304.         }  
  305.     }  
  306.       
  307.     /** 
  308.      * test 
  309.      * @throws InterruptedException  
  310.      */  
  311.     public static void main(String[] args) throws InterruptedException{  
  312.         StopWatch first = new StopWatch("First");  
  313.         first.start("A");  
  314.         Thread.sleep(200);  
  315.         first.stop();  
  316.         first.start("B");  
  317.         Thread.sleep(200);  
  318.         first.stop();  
  319.         first.start("C");  
  320.         Thread.sleep(120);  
  321.         first.stop();  
  322.         System.out.println(first.prettyPrint());  
  323.           
  324.     }  
  325. }  

执行结果如下:

[plain] view plain copy
  1. StopWatch 'First': running time (millis) = 516  
  2. -----------------------------------------  
  3. ms     %     Task name  
  4. -----------------------------------------  
  5. 00203  039%  A  
  6. 00203  039%  B  
  7. 00110  021%  C  
打印每个任务执行时间,以及占总时间百分比,个人开发测试时挺有用的,可以作为小工具收藏。