Guava Stopwatch源码分析

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].
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章