2013-07-11 3 views
4

Мы хотим запустить задачу каждые 1000 секунд (скажем).Что должен делать Timertask.scheduleAtFixedRate, если часы меняются?

Таким образом, мы имеем

timer.scheduleAtFixedRate(task, delay, interval); 

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

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

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

+0

если вы установите время вперед 3 дня, оно выполняет бесконечность (не совсем, но вы знаете, что я имею в виду) раз, пытаясь догнать !! – pstanton

ответ

11

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

Однако l ooking у источника 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.

+2

+1 Смотрел на источник и пришел к такому же выводу. Вероятно, это должно быть документировано немного лучше. – assylias

+0

Похоже, что мне нужно, но это Java 1.5 или выше. Мы должны использовать 1.4 :(Backports (JSR-166) существуют, но все еще полагаются на какие-то часы реального времени, на которые не влияют изменения в настройках даты/времени. Все еще смотря, чтобы увидеть, существует ли такая вещь в нашей среде ... –

+0

Ужасно, я вообще не делаю 1.4 :(Я знаю пакет с именем backport-util-concurrent, но действительно 'System.nanoTime()' это другое дело ... Если 1.4, я думаю, только нативный код может обеспечить это. – fge

3

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

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

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

+1

«Аналогично, когда системные часы установлены на более позднее время, задача может выполняться несколько раз». Это, похоже, зависит. У нас есть система IBM j9, где это, похоже, не происходит, но вместо этого он срабатывает один раз, через некоторое время не обязательно связанный с периодом повторения, а затем повторяется, как ожидалось. Однако мы еще не охарактеризовали это полностью. Мы смотрим на переход в ScheduledExecutorService –

+0

Хорошо, это интересно. Java в Windows. –