开发者

Will System.currentTimeMillis always return a value >= previous calls?

https://docs.oracle.com/javase/6/docs/a开发者_开发问答pi/java/lang/System.html#currentTimeMillis() says:

Returns the current time in milliseconds. Note that while the unit of time of the return value is a millisecond, the granularity of the value depends on the underlying operating system and may be larger. For example, many operating systems measure time in units of tens of milliseconds.

It is not clear to me if I am guaranteed that this code will always print ever increasing (or the same) numbers.

while (1) { 
    System.out.println(System.currentTimeMillis() );
}


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.


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.


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.


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)


@Mark Rushakoff is right; nanoTime() might be slightly more reliable.

Addendum: note these caveats, cited by @Steven Schlansker.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜