Detect if system time has been moved back to java or timers

I have a field using ntp, and we have several java programs running on them that display the clock. The problem we are facing is that sometime our system timers hit all of our timers, which do things like wait for the clock to stop, and wait until the system time returns to where it was. I need to find a way to detect when the system time was changed back, and reset all of our timers or a set of timers that can schedule multiple times, but still be proof against changing the clock.

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

+6
java timer
source share
2 answers

Almost all timers set the future time, and then regularly compare the current time with a given time. This is why timers β€œstop” when in real time it goes backward.

Unfortunately, ALL timers in the JVM are associated with the time of day. For example, java.util.Timer executes Object.wait (milliseconds) to fire an event. It comes down to invoking a thread that also waits for t milliseconds. And this is always relative to the "time of day".

So, in principle, there is no real way to do this in java without rotation, that is, a processor sucking loop waiting for time to go back to tell the timers you care about reset.

+5
source share

It seems that the clock widget is what is broken. The user interface widget should display the current state of the model, where the model in this case is the system time. Of course, for the clock, you need to schedule repaint() every second, but when repainting occurs, it should display the system time, and not try to track the time.

This principle applies even to components other than the UI. Determine the tolerance of the component for synchronization errors and get a background thread that updates the component at this interval. During the upgrade, however, the system time is used rather than the independent internal clock.


Update:

The main ScheduledExecutorService does not 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); 
+1
source share

All Articles