001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019package org.apache.hadoop.util; 020 021import java.io.Closeable; 022import java.util.concurrent.TimeUnit; 023 024/** 025 * A simplified StopWatch implementation which can measure times in nanoseconds. 026 */ 027public class StopWatch implements Closeable { 028 private final Timer timer; 029 private boolean isStarted; 030 private long startNanos; 031 private long currentElapsedNanos; 032 033 public StopWatch() { 034 this(new Timer()); 035 } 036 037 /** 038 * Used for tests to be able to create a StopWatch which does not follow real 039 * time. 040 * @param timer The timer to base this StopWatch's timekeeping off of. 041 */ 042 public StopWatch(Timer timer) { 043 this.timer = timer; 044 } 045 046 /** 047 * The method is used to find out if the StopWatch is started. 048 * @return boolean If the StopWatch is started. 049 */ 050 public boolean isRunning() { 051 return isStarted; 052 } 053 054 /** 055 * Start to measure times and make the state of stopwatch running. 056 * @return this instance of StopWatch. 057 */ 058 public StopWatch start() { 059 if (isStarted) { 060 throw new IllegalStateException("StopWatch is already running"); 061 } 062 isStarted = true; 063 startNanos = timer.monotonicNowNanos(); 064 return this; 065 } 066 067 /** 068 * Stop elapsed time and make the state of stopwatch stop. 069 * @return this instance of StopWatch. 070 */ 071 public StopWatch stop() { 072 if (!isStarted) { 073 throw new IllegalStateException("StopWatch is already stopped"); 074 } 075 long now = timer.monotonicNowNanos(); 076 isStarted = false; 077 currentElapsedNanos += now - startNanos; 078 return this; 079 } 080 081 /** 082 * Reset elapsed time to zero and make the state of stopwatch stop. 083 * @return this instance of StopWatch. 084 */ 085 public StopWatch reset() { 086 currentElapsedNanos = 0; 087 isStarted = false; 088 return this; 089 } 090 091 /** 092 * @return current elapsed time in specified timeunit. 093 */ 094 public long now(TimeUnit timeUnit) { 095 return timeUnit.convert(now(), TimeUnit.NANOSECONDS); 096 097 } 098 099 /** 100 * @return current elapsed time in nanosecond. 101 */ 102 public long now() { 103 return isStarted ? 104 timer.monotonicNowNanos() - startNanos + currentElapsedNanos : 105 currentElapsedNanos; 106 } 107 108 @Override 109 public String toString() { 110 return String.valueOf(now()); 111 } 112 113 @Override 114 public void close() { 115 if (isStarted) { 116 stop(); 117 } 118 } 119}