Reputation: 1949
I have a simple clock thread that updates the time once per second. In order to achieve that, I used Thread.sleep(1000)
to call the worker class every 1 second however, it seems like the clock runs slightly faster than my computer clock. Is there a way to normalize the sleep clock so that it will wake up exactly in a second, same with my computer clock?
Upvotes: 1
Views: 1497
Reputation: 2423
Idea is to go to sleep, wake up(possibly prematurely) and check time again to go to sleep.
Under heavy system load, your timer thread does not get scheduled and thread may not wake up from sleep resulting your clock going off time.
But its always about showing correct time, whenever possible.
General suggestion: maximize sleep to keep wake ups minimum(each wakeup involves one context switch).
Here is something I wrote for myself:
/**
* Put the calling thread to sleep.
* Note, this thread does not throw interrupted exception,
* and will not return until the thread has slept for provided time.
*
* @param milliSecond milliSecond time to sleep in millisecond
*/
public static void sleepForcefully(int milliSecond) {
final long endingTime = System.currentTimeMillis() + milliSecond;
long remainingTime = milliSecond;
while (remainingTime > 0) {
try {
Thread.sleep(remainingTime);
} catch (InterruptedException ignore) {
}
remainingTime = endingTime - System.currentTimeMillis();
}
}
This type of logic is used all over timers, pingers, etc in JDK and other places.
Upvotes: 0
Reputation: 52185
This should be expected, as per the JavaDoc:
Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds, subject to the precision and accuracy of system timers and schedulers. The thread does not lose ownership of any monitors.
What you could do, could be to sleep less, say, 400ms and then check to see if the time has changed.
Alternatively, you could use a Timer
and fire events once every second and update your time.
Edit: As per your comment, you could do something like so:
long initTime = System.getTimeinMillis();
while(true)
{
Thread.sleep(200);
if((System.getTimeInMillis() - initTime) >= 1000)
{
initTime = System.getTimeInMillis();
//Update your timer.
}
}
Upvotes: 2