Stopwatch

介绍
*简单的秒表,允许一些任务的计时,显示总计
*每个命名任务的运行时间和运行时间。
*
*

隐藏{@link System#nanoTime()}的使用,提高
*应用程序代码和减少计算错误的可能性。
*
*

请注意,此对象不是为线程安全而设计的,并且不使用
*同步。
*
*

该类通常用于验证概念验证期间的性能
*在开发中工作,而不是作为生产应用的一部分。
*
*

从Spring Framework 5.2开始,跟踪并报告运行时间
*纳秒。

使用

StopWatch stopWatch = new StopWatch();
stopWatch.start("taskname");
//somemethod;
stopWatch.stop();
System.out.println(stopWatch.getLastTaskName() + "=========" + stopWatch.getTotalTimeMillis());

源码分析
构造方法

/*
    1.这里的id是可以重复的,只是StopWatch实例的一个标识
    2.无参构造会默认调用有参构造,id取空字符串
*/

/**
 * Construct a new {@code StopWatch}.
 * <p>Does not start any task.
 */
public StopWatch() {
   this("");
}

/**
 * Construct a new {@code StopWatch} with the given ID.
 * <p>The ID is handy when we have output from multiple stop watches and need
 * to distinguish between them.
 * <p>Does not start any task.
 * @param id identifier for this stop watch
 */
public StopWatch(String id) {
   this.id = id;
}

开始,停止

/*
    start
    1.start()方法也会默认taskName是空字符串,调用有参方法
    2.通过this.currentTaskName是否为null来判断当前有没有正在计时的任务,这里并没有创建一个int变量空置,感觉是为了节省变量,省内存
    3.currentTaskName,startTimeNanos用来记录当前的任务的名称和开始时间,这里任务名称也是可以重复的
*/


/**
 * Start an unnamed task.
 * <p>The results are undefined if {@link #stop()} or timing methods are
 * called without invoking this method first.
 * @see #start(String)
 * @see #stop()
 */
public void start() throws IllegalStateException {
   start("");
}

/**
 * Start a named task.
 * <p>The results are undefined if {@link #stop()} or timing methods are
 * called without invoking this method first.
 * @param taskName the name of the task to start
 * @see #start()
 * @see #stop()
 */
public void start(String taskName) throws IllegalStateException {
   if (this.currentTaskName != null) {
      throw new IllegalStateException("Can't start StopWatch: it's already running");
   }
   this.currentTaskName = taskName;
   this.startTimeNanos = System.nanoTime();
}


/*
    stop:Stopwatch只能单个单个任务记录时间,串行的,这也是一个缺点
    1.通过System记录当前任务执行时间
    2.记录总的运行时间,总的任务数
    3.如果keepTaskList为true,将当前任务记录到队列中,注意当记录百万级时,这里的记录队列是有可能内存泄漏的
    4.将当前任务名称设置为null,初始化当前任务
*/


/**
 * Stop the current task.
 * <p>The results are undefined if timing methods are called without invoking
 * at least one pair of {@code start()} / {@code stop()} methods.
 * @see #start()
 * @see #start(String)
 */
public void stop() throws IllegalStateException {
   if (this.currentTaskName == null) {
      throw new IllegalStateException("Can't stop StopWatch: it's not running");
   }
   long lastTime = System.nanoTime() - this.startTimeNanos;
   this.totalTimeNanos += lastTime;
   this.lastTaskInfo = new TaskInfo(this.currentTaskName, lastTime);
   if (this.keepTaskList) {
      this.taskList.add(this.lastTaskInfo);
   }
   ++this.taskCount;
   this.currentTaskName = null;
}

格式化输出

/*
    1.shortSummary()只输出当前任务的id和运行时间
    2.prettyPrint()格式化输出队列当中的所有任务,运行时间、占比、名称
*/



/**
 * Get a short description of the total running time.
 */
public String shortSummary() {
   return "StopWatch '" + getId() + "': running time = " + getTotalTimeNanos() + " ns";
}

/**
 * Generate a string with a table describing all tasks performed.
 * <p>For custom reporting, call {@link #getTaskInfo()} and use the task info
 * directly.
 */
public String prettyPrint() {
   StringBuilder sb = new StringBuilder(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);
      for (TaskInfo task : getTaskInfo()) {
         sb.append(nf.format(task.getTimeNanos())).append("  ");
         sb.append(pf.format((double) task.getTimeNanos() / getTotalTimeNanos())).append("  ");
         sb.append(task.getTaskName()).append("\n");
      }
   }
   return sb.toString();
}
posted @ 2020-05-14 09:11  蒙多~想去哪就去哪  阅读(129)  评论(0)    收藏  举报