2010-08-12 73 views
6

我有一个使用ntp的盒子,我们有几个运行它们的java程序显示时钟。我们遇到的问题是,如果有什么东西把系统时间倒退,我们所有的计时器都会做动画停止,并等待系统时间恢复到原来的位置。我需要找到一种方法来检测系统时间是否已经改变,并重置所有定时器或一组定时器,这些定时器可以重复调度,但仍然可以防止时钟改变。检测系统时间是否已在java中向后移动,或者使用时间校验定时器

作为一个说明,我已经尝试过石英计时器包,它与普通的java定时器有相同的问题。

+0

时钟走多远? ntp通常使用时钟摆动来双向驱动时钟,并且不需要将其改变大量的秒数。 – Gray 2010-08-12 17:37:58

+0

系统中有一些错误将时间推后3到4小时。几乎就像我们有两个不同意的竞争ntp服务器。 – tharris 2010-08-14 14:25:08

回答

5

几乎所有的计时器设置未来的时间,然后定期比较当前时间和给定的时间。这就是为什么当实时倒退时计时器“失速”。

不幸的是,JVM中的所有定时器都与一天中的时间有关。例如,java.util.Timer为事件触发一个Object.wait(毫秒)。这归结为一个线程调用,也可以等待t毫秒。它总是相对于“一天中的时间”。

所以,基本上没有真正的方法可以在没有旋转的情况下在java中执行此操作,CPU吸入循环等待时间后退,以通知您要重置的计时器。

+0

是的,这就是我想出来的,但是我发现Thread.sleep()不受系统时钟改变的影响,所以我想我可以有一个睡眠时间为1然后检查时间是否已经倒退。 – tharris 2010-08-14 14:27:15

1

听起来像时钟小部件是什么坏了。 UI小部件应该显示模型的当前状态,在这种情况下,模型是系统时间。当然,对于一个时钟,你需要每秒安排一次repaint(),但是当发生重绘时,它应该呈现系统时间,而不是试图追踪时间本身。

这个原则甚至适用于非UI组件。确定组件对时间错误的容忍度,并有一个后台线程刷新该时间间隔内的组件。然而,在刷新期间,使用系统时间,而不是独立的内部时钟。


更新:

基本ScheduledExecutorService不存在这个问题,至少在我的平台上。

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

问题不在于widgit试图追踪时间本身,它每秒调用一次新的Date(),如果将系统时间向后移动,那么实际更新/设置时钟的java定时器会暂停执行直到该系统可以恢复到之前的状态。 – tharris 2010-08-14 14:29:17

+0

@tharris - 我明白了;我以前没有遇到过这个问题。然而,我使用的'ScheduledExecutorService'实现似乎不受问题影响,并且具有类似于Timer类的API(尽管它是更新且更健壮的java.util.concurrent包的一部分)。查看我的更新以获取示例。 – erickson 2010-08-18 07:53:55

+0

@erickson :(这不适用于Ubuntu 11.10 Java 6更新26.我现在也有同样的问题http://stackoverflow.com/questions/9044423/java-scheduler-which-is-completely-independent-of - 系统时间变化 – YoK 2012-01-28 11:52:54

相关问题