一、简介
StopWatch是java中的一个类库,翻译成中文是秒表的意思,顾名思义它的功能就是计时。
如上图,可见有很多个实现类库,api有些许差别,com.google.common.base.Stopwatch相比之下一些api更加灵活,因此项目中选用的是该Stopwtach。
二、为什么用StopWatch
计时功能常常在日志中用到,之前我们常用到的是:System.currentTimeMillis();
这里举例一个计算方法执行时间功能,代码如下:
@Test
public void test1() throws InterruptedException {
long start = System.currentTimeMillis();
Thread.sleep(1000);
long end1 = System.currentTimeMillis();
System.out.println((start - end1) / 1000);
Thread.sleep(1000);
long end2 = System.currentTimeMillis();
System.out.println((start - end2) / 1000);
}
相比之下StopWatch更加优雅:
@Test
public void test2() throws InterruptedException {
Stopwatch started = Stopwatch.createStarted();
Thread.sleep(1000);
System.out.println(started.elapsed(TimeUnit.SECONDS));
Thread.sleep(1000);
System.out.println(started.elapsed(TimeUnit.SECONDS));
}
就好像秒表按很多下计时键一样,统计出执行到每个步骤时消耗的时间。
三、怎么用
1.获取实例
获取Stopwatch有两种方式,分别是createUnstarted和createStarted
- createUnstarted:只是获取一个Stopwatch实例
- createStarted(常用) :获取一个Stopwatch实例,并立即开始计时
2.elapsed(TimeUnit desiredUnit)
返回Stopwatch经过的时间(可以指定返回的时间单位)
3.isRunning
判断计时器是否在运行状态
4.start
启动Stopwatch
5.stop
停止Stopwatch
6.reset
时间设置为0,状态设置为静止
四、源码
1.几个成员变量
//时间源
private final Ticker ticker;
//运行状态
private boolean isRunning;
//计时器stop前记录的时间
private long elapsedNanos;
//计时器开启时的时间
private long startTick;
2.Ticker类
看上去没有什么可以灵活配置的地方
public abstract class Ticker {
protected Ticker() {}
public abstract long read();
@CheckReturnValue
public static Ticker systemTicker() {
return SYSTEM_TICKER;
}
private static final Ticker SYSTEM_TICKER =
new Ticker() {
@Override
public long read() {
//实现就是System.nanoTime();
return Platform.systemNanoTime();
}
};
}
3.实例创建
即调用工厂方法实例化一个Ticker赋值自己的实例变量ticker,started方法直接调用start方法。
public static Stopwatch createStarted() {
return new Stopwatch().start();
}
public static Stopwatch createUnstarted() {
return new Stopwatch();
}
Stopwatch() {
this.ticker = Ticker.systemTicker();
}
4.start
public Stopwatch start() {
checkState(!isRunning, "This stopwatch is already running.");
//计时器标记为启动
isRunning = true;
//获取当前系统时间作为startTick
startTick = ticker.read();
return this;
}
5.stop
public Stopwatch stop() {
//获取当前系统时间
long tick = ticker.read();
checkState(isRunning, "This stopwatch is already stopped.");
//计时器标记为停止
isRunning = false;
//记录一下暂停前记录的时间
elapsedNanos += tick - startTick;
return this;
}
6.elapsed
public long elapsed(TimeUnit desiredUnit) {
//把时间转换为制定的单位
return desiredUnit.convert(elapsedNanos(), NANOSECONDS);
}
//最后返回的就是当前计时的时间
private long elapsedNanos() {
//如果在运行,返回:(当前时间-最近一次开始时间)+最近一次开始前记录的时间
//如果不在运行,返回记录的暂停前记录的时间
return isRunning ? ticker.read() - startTick + elapsedNanos : elapsedNanos;
}
7.reset
public Stopwatch reset() {
//暂停前记录的时间置为0
elapsedNanos = 0;
//运行状态置为停止
isRunning = false;
return this;
}