Stopwatch
很多library都有類似Stopwatch的實現,用來計算經過的時間,相當於一個計時器。
package com.google.common.base;
@GwtCompatible(emulated = true)
public final class Stopwatch {
private final Ticker ticker;
// 是否運行,start方法將其置爲true
private boolean isRunning;
// 花費時間
private long elapsedNanos;
// 開始時間
private long startTick;
/**
* 創建Stopwatch但是不啓動
*/
public static Stopwatch createUnstarted() {
return new Stopwatch();
}
/**
* 傳入一個tricker創建Stopwatch,不啓動
*/
public static Stopwatch createUnstarted(Ticker ticker) {
return new Stopwatch(ticker);
}
/**
* 創建Stopwatch並啓動
*/
public static Stopwatch createStarted() {
return new Stopwatch().start();
}
/**
* 傳入一個tricker創建Stopwatch並啓動
*/
public static Stopwatch createStarted(Ticker ticker) {
return new Stopwatch(ticker).start();
}
// 構造方法
Stopwatch() {
// sysTicker返回一個Tiker內部實現類
this.ticker = Ticker.systemTicker();
}
Stopwatch(Ticker ticker) {
this.ticker = checkNotNull(ticker, "ticker");
}
/**
* 返回isRunning標誌位
*/
public boolean isRunning() {
return isRunning;
}
/**
* 開始
*/
@CanIgnoreReturnValue
public Stopwatch start() {
// 不能重複start
checkState(!isRunning, "This stopwatch is already running.");
isRunning = true;
// 返回start時的系統時間
startTick = ticker.read();
return this;
}
/**
* 停止
*/
@CanIgnoreReturnValue
public Stopwatch stop() {
// 獲取end時系統時間
long tick = ticker.read();
// 不能重複stop
checkState(isRunning, "This stopwatch is already stopped.");
isRunning = false;
// end-start=耗費的時間
elapsedNanos += tick - startTick;
return this;
}
/**
* 重置Stopwatch
*/
@CanIgnoreReturnValue
public Stopwatch reset() {
elapsedNanos = 0;
isRunning = false;
return this;
}
/**
* 如果未stop,返回當前所用時間
* 如果已stop,返回所用時間
*/
private long elapsedNanos() {
return isRunning
? ticker.read() - startTick + elapsedNanos : elapsedNanos;
}
/**
* 用指定時間單位返回所用時間,時間四捨五入
*/
public long elapsed(TimeUnit desiredUnit) {
return desiredUnit.convert(elapsedNanos(), NANOSECONDS);
}
/**
* 返回時間,不丟失精度
*/
@GwtIncompatible
@J2ObjCIncompatible
public Duration elapsed() {
return Duration.ofNanos(elapsedNanos());
}
/**
* Returns a string representation of the current elapsed time.
*/
@Override
public String toString() {
long nanos = elapsedNanos();
// 選擇合適的時間單位
TimeUnit unit = chooseUnit(nanos);
double value = (double) nanos / NANOSECONDS.convert(1, unit);
// 格式化輸出字符串
return Platform
.formatCompact4Digits(value) + " " + abbreviate(unit);
}
// 根據轉換之後的數值選擇合適的時間單位
private static TimeUnit chooseUnit(long nanos) {
if (DAYS.convert(nanos, NANOSECONDS) > 0) {
return DAYS;
}
if (HOURS.convert(nanos, NANOSECONDS) > 0) {
return HOURS;
}
if (MINUTES.convert(nanos, NANOSECONDS) > 0) {
return MINUTES;
}
if (SECONDS.convert(nanos, NANOSECONDS) > 0) {
return SECONDS;
}
if (MILLISECONDS.convert(nanos, NANOSECONDS) > 0) {
return MILLISECONDS;
}
if (MICROSECONDS.convert(nanos, NANOSECONDS) > 0) {
return MICROSECONDS;
}
return NANOSECONDS;
}
// 添加單位
private static String abbreviate(TimeUnit unit) {
switch (unit) {
case NANOSECONDS:
return "ns";
case MICROSECONDS:
return "\u03bcs"; // μs
case MILLISECONDS:
return "ms";
case SECONDS:
return "s";
case MINUTES:
return "min";
case HOURS:
return "h";
case DAYS:
return "d";
default:
throw new AssertionError();
}
}
}
Tiker。
package com.google.common.base;
@Beta
@GwtCompatible
public abstract class Ticker {
protected Ticker() {}
/**
* 返回自此標記器的固定引用點以來經過的納秒數
*/
@CanIgnoreReturnValue // TODO(kak): Consider removing this
public abstract long read();
/**
* 返回內部實現類實例
*/
public static Ticker systemTicker() {
return SYSTEM_TICKER;
}
private static final Ticker SYSTEM_TICKER =
new Ticker() {
// 返回當前系統時間
@Override
public long read() {
return Platform.systemNanoTime();
}
};
}
使用
package com.xucc.guava.utilities;
import com.google.common.base.Stopwatch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.TimeUnit;
/**
* @author Created by xuche
* @date on 2019/7/3
*/
public class StopWatchExample {
private final static Logger LOGGER =
LoggerFactory.getLogger(StopWatchExample.class);
public static void main(String[] args) throws InterruptedException {
processOrder("10");
}
/**
* 處理指定訂單號訂單,並打印處理訂單期間所花費的時間
*/
private static void processOrder(String orderNo) throws InterruptedException {
LOGGER.info("start process the order [{}].", orderNo);
Stopwatch stopwatch = Stopwatch.createStarted();
TimeUnit.SECONDS.sleep(1);
LOGGER.info("the order [{}] process successful and elapsed [{}].", orderNo, stopwatch.stop());
}
}
輸出:
2019-07-04 11:16:55.291 [main] INFO c.x.guava.utilities.StopWatchExample - start process the order [10].
2019-07-04 11:16:55.575 [main] INFO c.x.guava.utilities.StopWatchExample - the order [10] process successful and elapsed [11.95 μs].