开发者

Detect if system time has been moved backwards in java, or time proof timers

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 li开发者_JAVA百科ke 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.


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.


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);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜