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].