检测java中系统时间是否向后移动,或者时间证明定时器

发布于 2024-09-14 06:09:47 字数 219 浏览 1 评论 0原文

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

作为注释,我已经尝试过石英定时器包,它与常规 java 定时器有相同的问题。

I have a box thats using ntp and we have several java programs running on them that display a clock. The problem we are having is if anything kicks the system time backwards all our timers that do things like animate the clock stop and wait until the system time catches back up to where it was. I need to find a way to either detect when the system time has been changed backwards and reset all our timers or a set of timers that can schedule repeatedly but still be proof against the clock changing.

As a note I already tried the quartz timer package it has the same problem as the regular java timers.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

等你爱我 2024-09-21 06:09:47

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

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

所以,基本上没有真正的方法可以在 java 中做到这一点,而不需要一个旋转的、CPU 消耗循环等待时间倒退,以通知您关心的计时器重置。

Pretty much all timers set a future time and then regularly compare current time to the given time. That's why timers "stall" when real time goes backward.

Unfortunately, ALL of the timers in the JVM are related to the time of day. For example, java.util.Timer does a Object.wait(milliSeconds) for an event to fire. That boils down to a thread call that also does a wait, for t milliseconds. And it's always relative to the "time of day".

So, basically there's no real way to do this in java without a spinning, CPU sucking loop waiting for the time to go backward in order to inform the timers you care about to reset.

小伙你站住 2024-09-21 06:09:47

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

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


更新:

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

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

It sounds like the clock widget is what's broken. A UI widget should display the current state of the model, where the model, in this case, is the system time. Sure, for a clock, you'd need to schedule a repaint() every second, but when the repaint occurs, it should render the system time, not try to keep track of the time itself.

This principle would apply even to non-UI components. Determine the tolerance of the component to timing errors, and have a background thread that refreshes the component at that interval. During a refresh, however, the system time is used, not an independent, internal clock.


Update:

The basic ScheduledExecutorService doesn't suffer from this problem, at least on my platform.

ScheduledExecutorService worker = Executors.newScheduledThreadPool(1);
worker.schedule(new Runnable() {
  public void run()
  {
    update();
  }
}, 100, TimeUnit.MILLISECONDS);
属性 2024-09-21 06:09:47

这已经是很久以后的事了,但可能对 Java 5 以来的当前情况有所帮助。

自 Java 5 天以来,我只有一个对我们的环境有帮助的建议:使用您自己的调试记录器或自定义正在使用的记录器以及每个日志项发布检查系统时间是否已从与 System.nanoTime() 中的自由运行时钟关联的已保存值向后或向前移动,并在该阶段保存当前时间和 System.nanoTime() 。如果您的计时器都是集中管理的(类似工厂),那么您也许可以重新安排所有这些时间。这对(隐藏)库计时器等没有帮助,但至少我们确实将时间跳转记录到调试输出中,并在某些情况下终止应用程序。这一切都要求记录器应该在线程进展时调用,而不是由计时器事件引起。

This is now ages later but might help in current situations since Java 5.

I only have a suggestion for something that does help in our environment since Java 5 days: use your own debug logger or customize the logger being used, and with each log item posted check whether the system time has moved back or forward from a saved value associated with the free-running clock from System.nanoTime(), saving the current time and System.nanoTime() at that stage. If your timers are all managed centrally (factory of sorts) then you might be able to reschedule all those times. This will not help with (hidden) library timers etc. but at least we do log the time jump to our debug output and in some cases terminates the application. This all requires that the logger should be called as threads progress and not caused by timer events.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文