2010-08-12 15 views
6

Tengo una caja que usa ntp y tenemos varios programas en ejecución que muestran un reloj. El problema que tenemos es que si todo hace retroceder al sistema, todos nuestros temporizadores hacen cosas como animar el reloj y esperar hasta que la hora del sistema vuelva a estar donde estaba. Necesito encontrar una forma de detectar cuando la hora del sistema se ha cambiado hacia atrás y reiniciar todos nuestros temporizadores o un conjunto de temporizadores que pueden programar repetidamente pero que aún así son a prueba contra el cambio de reloj.Detecta si la hora del sistema se ha movido hacia atrás en java, o temporizadores a prueba de tiempo

Como una nota que ya probé el paquete de temporizador de cuarzo tiene el mismo problema que los temporizadores de Java normales.

+0

¿Qué tan atrás está yendo el reloj? Por lo general, ntp usa la rotación del reloj para empujar el reloj en cualquier dirección y no debería necesitar cambiarlo en una gran cantidad de segundos. – Gray

+0

hay algún error en el sistema que está demorando tanto tiempo como 3 o 4 horas. Casi como si tuviéramos 2 servidores ntp competidores que no pueden estar de acuerdo. – tharris

Respuesta

5

Casi todos los temporizadores establecen un tiempo futuro y luego regularmente comparan la hora actual con el tiempo. Es por eso que los temporizadores "se paran" cuando el tiempo real retrocede.

Desafortunadamente, TODOS los temporizadores en la JVM están relacionados con la hora del día. Por ejemplo, java.util.Timer hace un Object.wait (milliSeconds) para que un evento se active. Eso se reduce a una llamada de subproceso que también espera, durante t milisegundos. Y siempre es relativo a la "hora del día".

Así que, básicamente, no hay una forma real de hacer esto en Java sin un ciclo de succión de CPU en espera de que el tiempo retroceda para informar a los temporizadores que desea reiniciar.

+0

Sí, eso es sobre lo que se me ocurrió, sin embargo, he encontrado que Thread.sleep() es inmune al reloj del sistema que se está modificando. Así que supongo que podría tener un hilo que duerme durante 1 segundo, luego verifica si el tiempo se ha movido hacia atrás. – tharris

1

Parece que el widget del reloj es lo que está roto. Un widget UI debe mostrar el estado actual del modelo, donde el modelo, en este caso, es la hora del sistema. Claro, para un reloj, necesitaría programar un repaint() por segundo, pero cuando ocurra el repintado, debería procesar la hora del sistema, no tratar de hacer un seguimiento de la hora en sí.

Este principio se aplicaría incluso a los componentes que no sean UI. Determine la tolerancia del componente a los errores de temporización y tenga una secuencia de fondo que actualice el componente en ese intervalo. Durante una actualización, sin embargo, se utiliza la hora del sistema, no un reloj interno independiente.


Actualización:

La básica ScheduledExecutorService no sufre este problema, al menos en mi plataforma.

ScheduledExecutorService worker = Executors.newScheduledThreadPool(1); 
worker.schedule(new Runnable() { 
    public void run() 
    { 
    update(); 
    } 
}, 100, TimeUnit.MILLISECONDS); 
+0

El problema no es que el widgit intente hacer un seguimiento del tiempo, sino que llama a Date() una vez por segundo, es que si mueve el tiempo del sistema hacia atrás, los temporizadores java que actualizan/animan el reloj pausan su ejecución hasta el sistema vuelve a estar donde estaba antes. – tharris

+0

@tharris - Ya veo; No me había encontrado con ese problema antes. Sin embargo, la implementación 'ScheduledExecutorService' que uso parece ser inmune al problema, y ​​tiene una API similar a la clase' Timer' (aunque es parte del paquete 'java.util.concurrent' más nuevo y mucho más robusto). Ver mi actualización para un ejemplo. – erickson

+0

@erickson :(esto no funciona con ubuntu 11.10 actualización de java 6 26. También tengo ahora la misma pregunta en http://stackoverflow.com/questions/9044423/java-scheduler-which-is-completely-independent-of -system-time-changes – YoK

Cuestiones relacionadas