Что должен делать 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, приостановив поток таймера и возобновив его.

Другие вопросы по тегам