tags:

views:

92

answers:

2

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.

+1  A: 

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);
erickson
The problem is not that the widgit is trying to keep track of time itself, it calls new Date() once a second, its that if you move system time backwards then the java timers that actually update/animate the clock pause their execution until the system catches back up to where it was before.
tharris
@tharris - I see; I hadn't run into that problem before. However, the `ScheduledExecutorService` implementation that I use seems to be immune to the problem, and has an API similar to the `Timer` class (although it's part of the newer and far more robust `java.util.concurrent` package). See my update for an example.
erickson
+2  A: 

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.

Will Hartung
Yea thats about what I'd come up with also, however I have found that Thread.sleep() is immune to the system clock being changed. So I guess I could have a thread that sleeps for 1 second then checks to see if time has moved backwards.
tharris