Reputation: 113
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.
Upvotes: 7
Views: 3200
Reputation: 1
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.
Upvotes: 0
Reputation: 269797
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);
Upvotes: 3
Reputation: 118714
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.
Upvotes: 5