Что должен делать Timertask.scheduleAtFixedRate, если часы меняются?
Мы хотим запускать задачу каждые 1000 секунд (скажем).
Итак, мы имеем
timer.scheduleAtFixedRate(task, delay, interval);
В основном это работает нормально. Однако это встроенная система, и пользователь может менять часы реального времени. Если они установили время в прошлом после того, как мы установили таймер, кажется, что таймер не будет работать до первоначальной даты / времени в реальном времени. Так что, если они установили его обратно на 3 дня, таймер не будет работать в течение 3 дней:(
Это допустимое поведение или дефект в библиотеке Java? В Oracle javadocs, похоже, ничего не говорится о зависимости или нет о значении системных часов.
Если это допустимо, как мы можем определить смену часов и перепланировать наши таймеры?
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.
Об этом сообщается здесь http://bugs.sun.com/view_bug.do?bug_id=4290274
Точно так же, когда системные часы установлены на более позднее время, задача может быть запущена несколько раз без какой-либо задержки, чтобы "догнать" пропущенные исполнения. Именно это происходит, когда компьютер находится в режиме ожидания / гибернации и приложение возобновляется (вот как я узнал).
Это поведение также можно увидеть в отладчике Java, приостановив поток таймера и возобновив его.