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