ScheduledThreadPoolExecutor выполняет неправильное время из-за несоответствия времени процессора
Я планирую задачу, используя объект ScheduledThreadPoolExecutor. Я использую следующий метод:
public ScheduledFuture<?> schedule(Runnable command, long delay,TimeUnit unit)
и установите задержку на 30 секунд (задержка = 30 000 и единица измерения =TimeUnit.MILLISECONDS). Иногда моя задача возникает сразу, а иногда это занимает 70 секунд.
Я считаю, что ScheduledThreadPoolExecutor использует специфичные для процессора часы. Когда я запускаю тесты, сравнивающие System.currentTimeMillis(), System.nanoTime() [который зависит от процессора], я вижу следующее
график: 1272637682651мс, 7858346157228410нс
выполнить: 1272637682667мс, 7858386270968425нс
разница составляет 16 мс, но 4011374001 нс (или 40,113 мс)
так что, похоже, что расхождение между двумя тактовыми частотами процессора составляет 40 секунд
Как решить эту проблему в коде Java? К сожалению, это клиентская машина, и я не могу изменить их систему.
1 ответ
Да, вы правы, что ScheduledThreadPoolExecutor использует System.nanoTime(). И вы также правы, что System.nanoTime () зависит от конкретного экземпляра системы. Если ваш процесс мигрирует между расписанием и выполнением, вам не повезло. (Я не думаю, что миграция между процессорами в многопроцессорной системе будет иметь значение, но, может быть, это имеет значение? Конечно, это будет иметь значение, если вы работаете в виртуальной машине, а виртуальная машина мигрирует между хостами).
Я думаю, что единственным реальным решением в этом случае является использование чего-то другого, кроме ScheduledThreadPoolExecutor... Это не так просто, как просто изменить ScheduledThreadPoolExecutor.now(). AbstractQueuedSynchronizer$ConditionObject.awaitNanos() также использует System.nanoTime().
Один из моих проектов использует Quartz для планирования заданий, и я никогда не видел проблемы, которую вы описываете с этой библиотекой. Я не знаю деталей реализации (может быть, он просто использует System.nanoTime (), но может и нет?).