It’s a Stopwatch. It keeps track of time.
How to use
Stopwatch stopwatch = Stopwatch.createStarted(); doSomething(); stopwatch.stop(); // optional long millis = stopwatch.elapsed(MILLISECONDS); // Formatted like "12.3ms "} log.info("time:" + stopwatch);Copy the code
Android use:
Stopwatch.createStarted(
new Ticker() {
public long read() {
return android.os.SystemClock.elapsedRealtime();
}
});}
Copy the code
Stopwatch execution time statistics can be implemented without Stopwatch, such as:
long startTime = System.currentTimeMillis(); Try {// Simulate business logic thread.sleep (1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(System.currentTimeMillis() - startTime);Copy the code
Yes, it is. It also counts the execution time of this code, so why Stopwatch (I have the same idea).
There are several reasons for not using System#nanoTime directly:
- Time sources can be used instead and Ticker can be overridden (described below)
- The return value of nanoTime is nanoseconds. The return value is meaningless. Stopwatch abstracts the return value
The following is an analysis of why Guava designed such a class from the implementation mode
Source code analysis
There are several member variables inside
// The time source is usually used with Stopwatch, not alone private final Ticker Ticker; private boolean isRunning; private long elapsedNanos; private long startTick;Copy the code
Let’s take a look at what Ticker has:
public static Ticker systemTicker() { return SYSTEM_TICKER; } private static final Ticker SYSTEM_TICKER = new Ticker() {@override public long read() {// actually system.nanotime (); return Platform.systemNanoTime(); }}; Public abstract Long read();Copy the code
Going back to Stopwatch, take a look at how it is constructed:
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"); }Copy the code
Including create do not start, create start construction
Execute the process
Start –> stop or reset
Look at the code. It’s very simple
Public Stopwatch start() {checkState(! isRunning, "This stopwatch is already running."); isRunning = true; // Initialize the current nanosecond time 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; }Copy the code
The code to get the result:
Private long elapsedNanos() {return isRunning? ticker.read() - startTick + elapsedNanos : elapsedNanos; } public Long Elapsed (TimeUnit desiredUnit) {return elapsed(elapsedNanos(), NANOSECONDS); }Copy the code
There are also some unit conversions and toString methods that I won’t analyze
conclusion
- Support for TimeUnit, which can be converted to various units such as stopwatch.Elapsed (timeunit.seconds).
- The same Stopwatch can be reset and repeated records
- Time sources can be substituted and Ticker can be overridden
- Other Spring implementations have similar StopWatch implementations, which do not support alternate time sources and can be reset. They support milliseconds and nanoseconds, but add the concept of Task