Что должен делать Timertask.scheduleAtFixedRate, если часы меняются?

Мы хотим запускать задачу каждые 1000 секунд (скажем).

Итак, у нас есть

timer.scheduleAtFixedRate(task, delay, interval);

В основном это нормально работает. Однако это встроенная система, и пользователь может изменить часы реального времени. Если они установили время в прошлом после того, как мы установили таймер, кажется, что таймер не будет работать до исходной даты / времени в реальном времени. Таким образом, если они установили его на 3 дня назад, таймер не сработает в течение 3 дней :(

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

Если это допустимо, как нам обнаружить это изменение часов и перенести наши таймеры?


person The Archetypal Paul    schedule 11.07.2013    source источник
comment
если вы установите время вперед на 3 дня, он будет выполнять бесконечное количество (не совсем, но вы понимаете, о чем я) раз, пытаясь наверстать упущенное !!   -  person pstanton    schedule 08.01.2018


Ответы (2)


Глядя на источник Timer для Java 1.7, кажется, что он использует System.currentTimeMillis() для определения следующего выполнения задачи.

Однако, если посмотреть на источник ScheduledThreadPoolExecutor, он использует System.nanoTime().

Это означает, что вы не увидите такого поведения, если используете его вместо Timer. Для его создания используйте, например, Executors.newScheduledThreadPool().

Почему вы не видите такого поведения, потому что в документе для System.nanoTime() написано:

Этот метод может использоваться только для измерения прошедшего времени и не связан с каким-либо другим понятием системного времени или времени настенных часов. Возвращаемое значение представляет собой наносекунды с некоторого фиксированного, но произвольного времени происхождения [выделено мной].

Что касается того, ошибка ли это в Timer, может быть ...

Обратите внимание, что в отличие от ScheduledExecutorService, Timer поддерживает абсолютное время, и, возможно, этим объясняется использование System.currentTimeMillis(); кроме того, Timer присутствует с Java 1.3, а System.nanoTime() появляется только в 1.5.

Но следствием использования System.currentTimeMillis() является то, что Timer чувствительно к системной дате / времени ... И это не задокументировано в javadoc.

person fge    schedule 11.07.2013
comment
+1 Посмотрел источник и пришел к такому же выводу. Вероятно, это следует задокументировать немного лучше. - person assylias; 11.07.2013
comment
Похоже, именно то, что мне нужно, но это Java 1.5 или выше. Мы должны использовать 1.4 :( Backports (из JSR-166) существуют, но по-прежнему полагаются на какие-то часы реального времени, на которые не влияют изменения в настройках даты / времени. Все еще ищем, существует ли такая вещь в нашей среде ... - person The Archetypal Paul; 16.07.2013
comment
Извините, я вообще не использую 1.4 :( Я знаю пакет с именем backport-util-concurrent, но на самом деле System.nanoTime() - другое дело ... Если 1.4, я думаю, это может обеспечить только собственный код. - person fge; 16.07.2013

Об этом сообщается здесь http://bugs.sun.com/view_bug.do?bug_id=4290274

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

Это поведение также можно увидеть в отладчике Java, приостановив поток таймера и возобновив его.

person Henno Vermeulen    schedule 31.07.2013
comment
Точно так же, когда системные часы установлены на более позднее время, задача может выполняться несколько раз. Кажется, это зависит. У нас есть система IBM j9, где этого, похоже, не происходит, но вместо этого она срабатывает один раз, через некоторое время, явно не связанное с периодом повтора, и впоследствии повторяется, как ожидалось. Однако мы еще не охарактеризовали это полностью. Мы планируем перейти на ScheduledExecutorService - person The Archetypal Paul; 31.07.2013
comment
Хорошо, это интересно. Мы используем Oracle Java в Windows. - person Henno Vermeulen; 01.08.2013