Defect -- When System Time Change
In product environment, system time may change, and we have to handle this kind of time change and do appropriate action.And in some JDK, problem may happen when system time is set ahead or back, such as in Thread.sleep, or Object.wait(long timeout), it may hang if time is set back, or it may end ahead of time.
This should be JDK bug, if you encounter this case, you may have to ask support from your JDK vendor.
In development and test, we should consider and cover this case.
In the following example, we set minimum time between queries - , if a notify occurred less than THROTTLE_TIME before the last query, it won't happen at this time.
But in original code, if system time is set 24 hours back , then in the next 24 hours, there would be no query at all.
public class StatusMonitorThread extends Thread {
private boolean running = true;
private static final long THROTTLE_TIME = 10000;
private long lastQueryTime = System.currentTimeMillis();
private boolean requeryNeeded = false;
private static final long TIME_DIFFERENCE_THRESHOLD = -5000;
public StatusMonitorThread() {}
public void run() {
while(running)
{
synchronized (this) {
try {
wait(THROTTLE_TIME);
} catch (InterruptedException e) {
System.out.println("interrupted...shutting down");
break;
}
// we suppose to limit frequency of query every THROTTLE_TIME seconds
// but if time is set back, for example 24 hours, then in next 24 hours,
// System.currentTimeMillis() - lastQueryTime would be less than 0,
// and in this 24 hours, requeryNeeded would remain false.
requeryNeeded = System.currentTimeMillis() - lastQueryTime > THROTTLE_TIME;
// the fix is simple, if System.currentTimeMillis() - lastQueryTime is less than 0,
// then system time must be set back, and if it the time difference is greater than one threshold,
// we can set requeryNeeded to true.
//change code above like this:
// long timeDiff = System.currentTimeMillis() - lastQueryTime;
// if(timeDiff > THROTTLE_TIME || timeDiff < TIME_DIFFERENCE_THRESHOLD)
// {
// requeryNeeded = true;
// }
if(requeryNeeded){
// do whatever you want
}
}
}
}
}