2012-01-28 2 views
17

Использует Java Timer, затем переключается на ScheduledExecutorService, но моя проблема не устранена. As Задачи, запланированные до изменения системного времени (через ntpd), не выполняются при указанной задержке. Не иметь логи же, как ничего не происходит :(Java-планировщик, который полностью не зависит от изменения системного времени

используя JRE 1.6.0_26 64 бит в моей цели на 64 битной Linux

Update:... ScheduledExecutorService отлично работает на Windows, проблема только на 64 разрядная система на базе Linux работает 64-битной JVM. Это отлично работает на 64 битном Linux под управлением 32-разрядную JVM ... странно. не нашли никаких ссылок на то же самое на любых блогах либо.

JAVA SDK IBM имеет те же проблемы (ibm-java-sdk-7.0-0.0-x86_64-archive.bin).

я подал дефект против JDK 7139684, он был принят, но был закрыт и отметился дублем 6900441. Пожалуйста, проголосуйте за него, если вы чувствуете, его стоит, чтобы ее исправить ... Я понятия не имею, почему его не было зафиксировано уже более двух лет

Вот пример кода, я использовал, чтобы проверить этот вопрос :

package test; 

import java.io.IOException; 
import java.util.Date; 
import java.util.concurrent.Executors; 
import java.util.concurrent.ScheduledExecutorService; 
import java.util.concurrent.TimeUnit; 

/** 
* @author yogesh 
* 
*/ 
public class TimerCheck implements Runnable { 

    ScheduledExecutorService worker; 


    public TimerCheck(ScheduledExecutorService worker) { 
     super(); 
     this.worker = worker; 
     this.worker.schedule(this, 1, TimeUnit.SECONDS); 
    } 

    private static void update() { 
     System.out.println("TimerCheck.update() "+new Date(System.currentTimeMillis())); 
    } 

    @Override 
    public void run() { 
      update(); 
      worker.schedule(this, 1, TimeUnit.SECONDS); 
    } 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     ScheduledExecutorService worker = Executors.newScheduledThreadPool(1); 
     new TimerCheck(worker); 
    } 

} 
+1

Этот образец кода отлично работает на моей машине ubuntu 11.10 [32 бит], JVM 1.6.0_21 [32 бит]. Изменение системных часов не влияет на выполнение. – Gopi

+0

да и проверял, что он отлично работает на 64-битном Linux-запуске 32-битного jvm :(. Обновил мой вопрос соответственно. – YoK

+1

Я хотел бы указать, что указание наносекундов в этом случае бессмысленно. Внутренне код в любом случае изменяется на миллисы. Итак, 'worker.schedule (это, 1000000000, TimeUnit.NANOSECONDS);' идентичен 'worker.schedule (это, 1, TimeUnit.SECONDS);' –

ответ

7

Существует bug in JVM для общего планирования во время Sytem изменения времени назад, что также влияет на очень простой Object.wait & Thread.sleep методы. Слишком рискованно поддерживать Java-приложение, когда системное время переключается на определенные секунды. Вы никогда не знаете, к чему приведет ваше приложение Java.

Итак, мы решили:

  • Написать сторожевую собаку сценарий (не Java :)), чтобы проверить изменение времени.
  • если время переключается на определенную сумму, выключается и перезапускается Java-приложение.

Другой возможностью было перейти на 32-битную JVM, но мы используем JNI, а затем собственные библиотеки, используемые на целевой платформе, не совместимы с 32-битной. Также из нашего опыта 32-битная JVM ограничивает нашу цель до кучи 1.6G, чего нам не хватает.

Я знаю, что наше не самое элегантное решение, но до тех пор, пока JVM не будет исправлена ​​или не найдено какое-либо лучшее решение, похоже, что нет другого пути.

Отредактировано: Мы также рассматриваем 1-ое предложение от Криса в дополнение к указанному выше раствору:

  • Настройка NTP, чтобы никогда не иметь большой скачок времени. Только убил время медленно. Используйте только длинные переходы вручную во время простоя.
+0

Принимать этот ответ в качестве обходного пути :(Пока все еще ждут правильного решения. – YoK

+0

Я не понимаю, насколько это сильно влияет на JVM. Из вашего aswer кажется, что это критическая ошибка. Например, если я использую Object.wait (1), и часы возвращаются назад - означает ли это, что поток никогда не может быть просыпаться? – BegemoT

+0

@BegemoT Это не значит, что он никогда не проснется ...Но он просыпается после (часы времени перемещаются назад + 1). что является опасным. И это происходит только на 64-битной JVM на 64-битном Linux. – YoK

2

Я работал против той же проблемы и не нашел решения. Я посмотрел на Кварц и все встроенные методы JRE. Методы нанотимов могут использовать монотонные часы на процессор, но вы рискуете большими прыжками, если потоки переносятся на другой ЦП, я полагаю. Мои выводы были следующими:

  1. Настроить NTP, чтобы никогда не было большого перерыва. Только медленно убил время. Используйте только длинные переходы вручную во время простоя.
  2. Используйте несколько коротких тайм-аутов и требуйте два таймаута, чтобы объявить удаленную машину мертвой. Это не поможет, если у вас есть только одна система синхронизации сама, но может помочь с несколькими системами
  3. использовать удаленный компьютер для отправки периодических пробуждений. Если ваши собственные часы идут назад между пробуждениями, то вы знаете, что все ваши таймеры собираются с опозданием.

В принципе, это огромная боль, но нет серебряных пуль.

+0

Но вы в конце концов применили любое из этих решений. Для меня это невозможно :) – YoK

+2

@YoK, да все три. Мой сценарий обнаруживал, когда/когда первичная служба умерла, поэтому резервная копия могла автоматически захватить. Во всех конфигурациях NTP, которые я использовал, было выполнено: если синхронизация находится в пределах N минут (скажем, 2), то медленно поворачивает часы к правильному времени со скоростью Х миллис в минуту (скажем, 20). Если синхронизация превышает N минут, то NTP выдает сообщение системного журнала об ошибке и переходит в пассивное состояние. –

+0

Интересно ... попросит моих парней NTP посмотреть на это. – YoK

Смежные вопросы