Will System.currentTimeMillis always return a value >= previous calls?
Solution 1:
The short answer is no, System.currentTimeMillis()
is not monotonic. It is based on system time, and hence can be subject to variation either way (forward or backward) in the case of clock adjustments (e.g. via NTP).
System.nanoTime()
is monotonic, if and only if the underlying platform supports CLOCK_MONOTONIC
-- see the comments on Java bug report 6458294 for a good writeup on some circumstances where this is/isn't true.
(And, as an additional anecdote, I have personally observed (several times) System.currentTimeMillis()
run 'backwards', in the absence of clock adjustments, across threads -- that is, a call to that method in one thread returned a lower value than a call in another thread, even though it occurred chronologically after it in 'real-time')
If you need a monotonic source, System.nanoTime()
on a platform supporting monotonicity is your best option.
Solution 2:
No, it will not always be >= all previous calls.
It might not increase every time if you call it several times in quick succession from the same thread (I know this is the = part of >=, but the behavior often surprises people).
If you call it several times in quick succession from multiple threads, it might do any number of things -- it could go slightly back in time across threads by a very small amount, depending on implementation and random chance.
Most seriously, the value might go back in time by a large amount if the user (rare) or an NTP sync (potentially common) adjusts the system clock.
Solution 3:
It couldn't possibly be guaranteed to be increasing, based on the fact that the user could potentially change the system time between calls.
Besides that, it should stay increasing since it represents milliseconds since the epoch. If it were a normal "wall time", you would have to worry about time changes on leap day or on daylight savings changeover.
Solution 4:
If you want a value which is monotonicly increasing you can do something like.
public enum Time {
;
private static long lastTime;
public synchronized static long increasingTimeMillis() {
long now = System.currentTimeMillis();
if (now > lastTime)
return lastTime = now;
return ++lastTime;
}
}
As long as you call this less than a thousand times per second, your increasing time won't drift too far from the real time but will be unique. (This can work, even if you restart your application)