Guava 中的 Stopwatch 是什么?

Stephen

共 3200字,需浏览 7分钟

 ·

2020-10-20 17:42

点击上方蓝色“Stephen”,选择“设为星标”


来源:https://my.oschina.net/lowkeysoft/blog/1595755



Stopwatch 解释为计时器,又称秒表、停表,很明显它是记录时间的。


# 如何使用


Stopwatch stopwatch = Stopwatch.createStarted();doSomething();stopwatch.stop(); long millis = stopwatch.elapsed(MILLISECONDS);// formatted string like "12.3 ms"log.info("time: " + stopwatch);

安卓使用:

Stopwatch.createStarted(         new Ticker() {           public long read() {             return android.os.SystemClock.elapsedRealtime();            }          });}

看了上面这段代码,有人会说,不用 Stopwatch 照样可以实现执行时间的统计,比如:

long startTime = System.currentTimeMillis();try {    // 模拟业务逻辑    Thread.sleep(1000);} catch (InterruptedException e) {    e.printStackTrace();}System.out.println(System.currentTimeMillis() - startTime);

确实是,这样也能统计这段代码的执行时间,那么为什么还会有 Stopwatch(我也有这种想法)


官方称不直接使用System#nanoTime是有一下几个原因:


  • 时间源可以替代 可以重写Ticker(下面会介绍)

  • nanoTime的返回值是纳秒,返回的值没有意义,Stopwatch抽象返回值


下面从实现方式来分析下guava为什么会设计这么类


# 源码分析


内部有几个成员变量

  //时间源 一般和Stopwatch一起使用,而不是单独使用  private final Ticker ticker;  private boolean isRunning;  private long elapsedNanos;  private long startTick;

先看下Ticker(是个abstract类) 都有什么:

  public static Ticker systemTicker() {    return SYSTEM_TICKER;  }
private static final Ticker SYSTEM_TICKER = new Ticker() { @Override public long read() { // 实际上就是System.nanoTime(); return Platform.systemNanoTime(); } }; // 子类重写    public abstract long read();

回到Stopwatch,看下它的构造方式:


  public static Stopwatch createUnstarted() {    return new Stopwatch();  }
/** * Creates (but does not start) a new stopwatch, using the specified time source. * * @since 15.0 */ public static Stopwatch createUnstarted(Ticker ticker) { return new Stopwatch(ticker); }
/** * Creates (and starts) a new stopwatch using {@link System#nanoTime} as its time source. * * @since 15.0 */ public static Stopwatch createStarted() { return new Stopwatch().start(); } Stopwatch() { this.ticker = Ticker.systemTicker(); }
Stopwatch(Ticker ticker) { this.ticker = checkNotNull(ticker, "ticker"); }
  

包括创建不启动,创建启动的构造方式


执行流程


start--> stop 或者 reset


看下代码,很简单

 public Stopwatch start() {    // 先判断是否处于执行状态    checkState(!isRunning, "This stopwatch is already running.");    isRunning = true;    // 初始化 当前的纳秒时间    startTick = ticker.read();    return this;  }
public Stopwatch stop() { long tick = ticker.read(); checkState(isRunning, "This stopwatch is already stopped."); isRunning = false; elapsedNanos += tick - startTick; return this; } public Stopwatch reset() { elapsedNanos = 0; isRunning = false; return this;  }

获取结果的代码:

  // 计算纳秒  private long elapsedNanos() {    return isRunning ? ticker.read() - startTick + elapsedNanos : elapsedNanos;  }
// 转换其他单位 public long elapsed(TimeUnit desiredUnit) { return desiredUnit.convert(elapsedNanos(), NANOSECONDS); }
还有一些单位转换和toString方法,就不分析了。


# 总结


  • 支持TimeUnit,可以将计算后的时间转换为各种单位 比如:stopwatch.elapsed(TimeUnit.SECONDS))

  • 同一个Stopwatch,可以重置,重复记录

  • 时间源可以替代 可以重写Ticker

  • 其他 Spring 也有StopWatch 实现方式差不多,不支持替换时间源和可以重置,支持毫秒和纳秒,但是增加了Task的概念



喜欢就三连


点击"阅读原文"可跳转至我的博客。



关注 Stephen,一起学习,一起成长。


浏览 26
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报