Будет ли System.currentTimeMillis всегда возвращать значение >= предыдущие вызовы?
http://java.sun.com/j2se/1.4.2/docs/api/java/lang/System.html#currentTimeMillis() говорит:
Возвращает текущее время в миллисекундах. Обратите внимание, что хотя единица времени возвращаемого значения равна миллисекунде, степень детализации зависит от базовой операционной системы и может быть больше. Например, многие операционные системы измеряют время в единицах десятков миллисекунд.
Мне не ясно, гарантирован ли, что этот код всегда будет печатать все увеличивающиеся (или одинаковые) номера.
while (1) {
System.out.println(System.currentTimeMillis() );
}
Ответы
Ответ 1
Короткий ответ - нет, System.currentTimeMillis()
не является монотонным. Он основан на системном времени и, следовательно, может быть изменен в любом случае (вперед или назад) в случае регулировки часов (например, через NTP).
System.nanoTime()
является монотонным, тогда и только тогда, когда базовая платформа поддерживает CLOCK_MONOTONIC
- см. комментарии к отчет об ошибке Java 6458294 для хорошая запись при некоторых обстоятельствах, когда это/неверно.
(И, как дополнительный анекдот, я лично наблюдал (несколько раз) System.currentTimeMillis()
запустил "назад", в отсутствие регулировки часов, по потокам - то есть, вызов этого метода в один поток вернулся более низкое значение, чем вызов в другом потоке, даже если он произошел в хронологическом порядке после него в режиме реального времени)
Если вам нужен монотонный источник, System.nanoTime()
на платформе, поддерживающей монотонность, является вашим лучшим вариантом.
Ответ 2
Нет, это не всегда будет >= все предыдущие вызовы.
-
Он может не увеличиваться каждый раз, если вы вызываете его несколько раз подряд из одного потока (я знаю, что это = часть > =, но поведение часто удивляет людей).
-
Если вы вызываете его несколько раз подряд из нескольких потоков, он может делать любое количество вещей - он может немного отстать во времени по потокам на очень небольшую сумму, в зависимости от реализации и случайной вероятности.
-
Наиболее серьезно, значение может вернуться во времени на большую сумму, если пользователь (редкий) или NTP-синхронизация (потенциально общий) настраивает системные часы.
Ответ 3
Невозможно гарантировать, что он будет увеличиваться, исходя из того, что пользователь может потенциально изменить системное время между вызовами.
Кроме того, он должен оставаться увеличивающимся, так как он представляет миллисекунды с эпохи. Если бы это было обычное "время на стене", вам пришлось бы беспокоиться о временных изменениях в високосный день или при переходе на летнее время.
Ответ 4
Если вы хотите монотонно увеличить значение, вы можете сделать что-то вроде.
public enum Time {
;
private static long lastTime;
public synchronized static long increasingTimeMillis() {
long now = System.currentTimeMillis();
if (now > lastTime)
return lastTime = now;
return ++lastTime;
}
}
Пока вы называете это менее тысячи раз в секунду, ваше увеличение времени не будет слишком далеко от реального времени, но будет уникальным. (Это может работать, даже если вы перезапустите приложение)
Ответ 5
@Марк Рушаков прав; nanoTime()
может быть немного более надежным.
Добавление: обратите внимание на предостережения, процитированные @Steven Schlansker.