• 代码块耗时统计工具-StopWatch详解


    一、最简单的计时 ----- 来源:https://www.jb51.net/article/166608.htm

    在我们的程序中不免需要对某一个运算或者方法进行计时,以便我们来观察该运算或方法是否符合我们的预期,所以在我们刚开始接触 Java 的时候都能写出类似下面这样的代码来计时:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public static void main(String[] args) {
      Long startTime = System.currentTimeMillis();
      doSomeThing();
      Long endTime = System.currentTimeMillis();
      Long elapsedTime = (endTime - startTime) / 1000;
      System.out.println("总共耗时:" + elapsedTime + "s");
    }
    // 用于模拟一些操作
    private static void doSomeThing() {
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }

    事实上这样也并没有什么问题,并且也能够运行的很好,但是有一点不太好的就是,自己关注了太多输出的信息,下面我们来认识一种更优雅的一种计时方式;

    二、StopWatch 类

    想要使用它,首先你需要在你的 Maven 中引入 Spring 核心包,当然 Spring MVC 和 Spring Boot 都已经自动引入了该包:

    1
    2
    3
    4
    5
    6
    <!-- spring核心包 -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${spring.version}</version>
    </dependency>

    现在我们计时的姿势或许就会变成以下这样:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    public static void main(String[] args) {
      StopWatch clock = new StopWatch();
     
      clock.start("开始任务一");
      doSomeThing();
      clock.stop();
     
      clock.start("开始任务二");
      doSomeThing();
      clock.stop();
     
      System.out.println(clock.prettyPrint());
    }
     
    // 用于模拟一些操作
    private static void doSomeThing() {
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }

    在最后我们使用 StopWatch 类自带的 prettyPrint() 方法类格式化我们的输出,运行程序你会发现你的程序输出了这样的东西:

    1
    2
    3
    4
    5
    6
    StopWatch '': running time (millis) = 2009
    -----------------------------------------
    ms   %   Task name
    -----------------------------------------
    01005 050% 开始任务一
    01004 050% 开始任务二

    不仅有总用时,还有每个任务分别的占用时间和占用时间的百分比,这或许就会比我们自己输出要优雅那么一些;

    StopWatch 类是怎么实现的呢?

    当你戳开 StopWatch 的源码,你会在总共不到 200 行的代码里看到熟悉的东西:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    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.startTimeMillis = System.currentTimeMillis();
      }
    }
     
    public void stop() throws IllegalStateException {
      if (this.currentTaskName == null) {
        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.currentTaskName = null;
      }
    }

    你会发现该类使用 LinkedList 实现了一个叫做 taskList 的队列,然后每一次开始同样也是使用 System.currentTimeMillis() 方法来获取时间,每次除了计算耗时也会构建一个描述当前任务的 TaskInfo 对象,并把它放入 taskList 队列中。

    当执行 prettyPrint() 方法的时候,就从 taskList 队列中依次取出任务,然后做些格式化的操作:

    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
    public String shortSummary() {
      return "StopWatch '" + this.getId() + "': running time (millis) = " + this.getTotalTimeMillis();
    }
     
    public String prettyPrint() {
      StringBuilder sb = new StringBuilder(this.shortSummary());
      sb.append(' ');
      if (!this.keepTaskList) {
        sb.append("No task info kept");
      } else {
        sb.append("----------------------------------------- ");
        sb.append("ms   %   Task name ");
        sb.append("----------------------------------------- ");
        NumberFormat nf = NumberFormat.getNumberInstance();
        nf.setMinimumIntegerDigits(5);
        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.getTimeMillis())).append(" ");
          sb.append(pf.format(task.getTimeSeconds() / this.getTotalTimeSeconds())).append(" ");
          sb.append(task.getTaskName()).append(" ");
        }
      }
     
      return sb.toString();
    }

    摁,新姿势 get √。

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

  • 相关阅读:
    POJ2376 Cleaning Shifts
    百度首页图标
    NOIP2016换教室
    CH3803扑克牌
    【POJ2723】Get Luffy Out
    【USACO13DEC】 最优挤奶
    【SP2916】Can you answer these queries V
    【线段树】各种模板集合
    【SCOI2013】摩托车交易
    【CF1174D】 Ehab and the Expected XOR Problem
  • 原文地址:https://www.cnblogs.com/fanheyan/p/13035785.html
Copyright © 2020-2023  润新知