【问题标题】:Detect if system time has been moved backwards in java, or time proof timers检测系统时间是否在java中向后移动,或时间证明计时器
【发布时间】:2010-08-18 15:54:49
【问题描述】:

我有一个使用 ntp 的盒子,我们在上面运行了几个显示时钟的 java 程序。我们遇到的问题是,如果有任何事情使系统时间倒退,我们所有的计时器都会执行诸如动画时钟停止之类的操作,并等待系统时间回到原来的位置。我需要找到一种方法来检测系统时间何时向后更改并重置我们所有的计时器或一组可以重复调度但仍然可以防止时钟更改的计时器。

请注意,我已经尝试过石英计时器包,它与常规 java 计时器有同样的问题。

【问题讨论】:

  • 时钟回了多远? ntp 通常使用时钟摆动来向任一方向微调时钟,并且不需要将其更改很多秒。
  • 系统中的一些错误将时间缩短了 3 或 4 小时。几乎就像我们有 2 个无法达成一致的竞争 ntp 服务器。

标签: java timer


【解决方案1】:

几乎所有计时器都会设置一个未来时间,然后定期将当前时间与给定时间进行比较。这就是为什么当实时倒退时计时器会“停止”。

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

因此,基本上没有真正的方法在 java 中执行此操作,而无需旋转、CPU 吸吮循环等待时间倒退以通知您关心的计时器重置。

【讨论】:

  • 是的,这也是我想出的,但是我发现 Thread.sleep() 不受系统时钟改变的影响。所以我想我可以让一个线程休眠 1 秒,然后检查时间是否向后移动。
【解决方案2】:

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

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


更新:

基本的ScheduledExecutorService 不会遇到这个问题,至少在我的平台上是这样。

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

【讨论】:

  • 问题不在于widgit试图自己跟踪时间,它每秒调用一次new Date(),如果你将系统时间向后移动,那么实际更新的java计时器/动画时钟暂停它们的执行,直到系统恢复到之前的位置。
  • @tharris - 我明白了;我以前没有遇到过这个问题。但是,我使用的ScheduledExecutorService 实现似乎不受该问题的影响,并且具有类似于Timer 类的API(尽管它是更新且更强大的java.util.concurrent 包的一部分)。以我的更新为例。
  • @erickson :( 这不适用于 ubuntu 11.10 java 6 update 26。我现在也有同样的问题 stackoverflow.com/questions/9044423/…
猜你喜欢
  • 1970-01-01
  • 2021-12-28
  • 1970-01-01
  • 1970-01-01
  • 2012-07-03
  • 1970-01-01
  • 2016-12-04
  • 1970-01-01
相关资源
最近更新 更多