u=2486381870,3695897862&fm=27&gp=0.jpg
是什么
Stopwatch 解釋為計(jì)時(shí)器肉拓,又稱秒表鸭丛、停表竞穷,很明顯它是記錄時(shí)間的。
如何使用
Stopwatch stopwatch = Stopwatch.createStarted();
doSomething();
stopwatch.stop(); // optional
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();
}
});}
看了上面這段代碼鳞溉,有人會(huì)說瘾带,不用Stopwatch 照樣可以實(shí)現(xiàn)執(zhí)行時(shí)間的統(tǒng)計(jì),比如:
long startTime = System.currentTimeMillis();
try {
// 模擬業(yè)務(wù)邏輯
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(System.currentTimeMillis() - startTime);
確實(shí)是熟菲,這樣也能統(tǒng)計(jì)這段代碼的執(zhí)行時(shí)間看政,那么為什么還會(huì)有Stopwatch(我也有這種想法)
官方稱不直接使用System#nanoTime是有一下幾個(gè)原因:
- 時(shí)間源可以替代 可以重寫Ticker(下面會(huì)介紹)
- nanoTime的返回值是納秒,返回的值沒有意義抄罕,Stopwatch抽象返回值
下面從實(shí)現(xiàn)方式來分析下guava為什么會(huì)設(shè)計(jì)這么類
源碼分析
內(nèi)部有幾個(gè)成員變量
//時(shí)間源 一般和Stopwatch一起使用允蚣,而不是單獨(dú)使用
private final Ticker ticker;
private boolean isRunning;
private long elapsedNanos;
private long startTick;
先看下Ticker(是個(gè)abstract類) 都有什么:
public static Ticker systemTicker() {
return SYSTEM_TICKER;
}
private static final Ticker SYSTEM_TICKER =
new Ticker() {
@Override
public long read() {
// 實(shí)際上就是System.nanoTime();
return Platform.systemNanoTime();
}
};
// 子類重寫
public abstract long read();
回到Stopwatch,看下它的構(gòu)造方式:
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");
}
包括創(chuàng)建不啟動(dòng)呆贿,創(chuàng)建啟動(dòng)的構(gòu)造方式
執(zhí)行流程
start--> stop 或者 reset
看下代碼嚷兔,很簡(jiǎn)單
public Stopwatch start() {
// 先判斷是否處于執(zhí)行狀態(tài)
checkState(!isRunning, "This stopwatch is already running.");
isRunning = true;
// 初始化 當(dāng)前的納秒時(shí)間
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;
}
獲取結(jié)果的代碼:
// 計(jì)算納秒
private long elapsedNanos() {
return isRunning ? ticker.read() - startTick + elapsedNanos : elapsedNanos;
}
// 轉(zhuǎn)換其他單位
public long elapsed(TimeUnit desiredUnit) {
return desiredUnit.convert(elapsedNanos(), NANOSECONDS);
}
還有一些單位轉(zhuǎn)換和toString方法,就不分析了
總結(jié)
- 支持TimeUnit,可以將計(jì)算后的時(shí)間轉(zhuǎn)換為各種單位
比如:stopwatch.elapsed(TimeUnit.SECONDS)) - 同一個(gè)Stopwatch谴垫,可以重置章母,重復(fù)記錄
- 時(shí)間源可以替代 可以重寫Ticker
- 其他
Spring 也有StopWatch 實(shí)現(xiàn)方式差不多,不支持替換時(shí)間源和可以重置翩剪,支持毫秒和納秒乳怎,但是增加了Task的概念