I am writing a stop watch utility class in Java that I want to be thread-safe (concurrent). Here is what I have right now:
public class Stopwatch {
private volatile long beginTime;
private final AtomicLong lastLap = new AtomicLong();
private final AtomicReference<List<Long>> laps = new AtomicReference<List<Long>>();
public synchronized void start() {
reset();
beginTime = System.nanoTime();
lastLap.set(beginTime);
}
public long timeElapsed() {
return toMilliseconds(timeElapsed(beginTime));
}
public void lap() {
long lap = timeElapsed(lastLap.longValue());
lastLap.addAndGet(lap);
getLaps().add(toMilliseconds(lap));
}
public synchronized void reset() {
beginTime = 0;
lastLap.set(0);
if (laps.get() != null) {
laps.get().clear();
}
}
public List<Long> getLaps() {
laps.compareAndSet(null, Collections.synchronizedList(new ArrayList<Long>()));
return laps.get();
}
private long toMilliseconds(long nano) {
return nano / 1000000;
}
private long timeElapsed(long start) {
return System.nanoTime() - start;
}
}
A few notes, the compareAndSet
call in getLaps
is used to lazily initialize the list. I added the synchronized
modifiers to the start
and reset
methods to prevent the scenario of multiple threads calling those methods simultaneously, which could possibly result in some fields being reset and some being initialized, giving odd behavior. I did not add the synchronized
modifiers to the other methods because I anticipate them to operate as expected even when invoked from multiple threads, though, quite frankly, I'm not entirely sure if that is the case.
I would like this implementation to avoid locking as much as possible because the locking and waiting could give slightly inaccurate results for certain methods, like timeElapsed
.
Do I need to make any modifications to make this class thread-safe?