Будет ли System.currentTimeMillis всегда возвращать значение> = предыдущие вызовы? - PullRequest
44 голосов
/ 05 июня 2010

http://java.sun.com/j2se/1.4.2/docs/api/java/lang/System.html#currentTimeMillis() говорит:

Возвращает текущее время в миллисекундах. Обратите внимание, что хотя единица времени возвращаемого значения составляет миллисекунду, степень детализации значения зависит от базовой операционной системы и может быть больше. Например, многие операционные системы измеряют время в десятках миллисекунд.

Мне не ясно, гарантирую ли я, что этот код будет всегда печатать постоянно увеличивающиеся (или одинаковые) числа.

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

Ответы [ 5 ]

57 голосов
/ 05 июня 2010

Короткий ответ - нет, System.currentTimeMillis() - это , а не монотонно. Он основан на системном времени и, следовательно, может изменяться в любом направлении (вперед или назад) в случае настройки часов (например, через NTP ).

System.nanoTime() является монотонным, если и только если базовая платформа поддерживает CLOCK_MONOTONIC - см. Комментарии к Отчет об ошибках Java 6458294 для хорошей записи при некоторых обстоятельствах, где это / нет правда.

(И, как дополнительный анекдот, я лично наблюдал (несколько раз) System.currentTimeMillis() запускать «назад», при отсутствии настроек часов, между потоками - то есть возвращался вызов этого метода в одном потоке более низкое значение, чем вызов в другом потоке, даже если он произошел в хронологическом порядке после него в режиме реального времени)

Если вам нужен монотонный источник, System.nanoTime() на платформе, поддерживающей монотонность, - ваш лучший вариант.

12 голосов
/ 05 июня 2010

Нет, это не всегда будет> = все предыдущие вызовы.

  • Может не увеличиваться каждый раз, если вы вызываете его несколько раз подряд в одном и том же потоке (я знаю, что это = часть> =, но поведение часто удивляет людей).

  • Если вы вызываете его несколько раз подряд из нескольких потоков, это может сделать любое количество вещей - он может немного отступить во времени между потоками на очень небольшую величину, в зависимости от реализации и случайного шанса.

  • Если серьезно, значение может значительно увеличиться во времени, если пользователь (редко) или синхронизация NTP (потенциально часто) настраивает системные часы.

9 голосов
/ 05 июня 2010

Это не может быть гарантированным увеличением , исходя из того факта, что пользователь потенциально может изменять системное время между вызовами.

Кроме того, оно должно продолжать расти, поскольку оно представляет миллисекунды с начала эпохи. Если бы это было обычное «настенное время», вам пришлось бы беспокоиться об изменениях времени в високосный день или при переходе на летнее время.

7 голосов
/ 05 июня 2010

Если вы хотите, чтобы значение монотонно увеличивалось, вы можете сделать что-то вроде.

public enum Time {
    ;
    private static long lastTime;
    public synchronized static long increasingTimeMillis() {
        long now = System.currentTimeMillis();
        if (now > lastTime)
            return lastTime = now;
        return ++lastTime;
    }
}

Пока вы вызываете это менее тысячи раз в секунду, ваше увеличивающееся время не будет слишком сильно отклоняться от реального времени, но будет уникальным. (Это может работать, даже если вы перезапустите приложение)

1 голос
/ 05 июня 2010

@ Марк Рушаков прав; nanoTime() может быть немного более надежным.

Приложение: обратите внимание на эти предостережения , цитируемые @Steven Schlansker.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...