ADDITIONAL SYSTEM INFORMATION :
All Window 10, current and earlier JVM's (it's been this way for at least four years).
A DESCRIPTION OF THE PROBLEM :
Given a desktop application that uses Thread.sleep() to achieve long (minutes or hours) delays, the application calculates how far in the future it needs to do something, then hits a Thread.sleep(msToWait). This has been working fine before Windows 8, even if the system happens to go into S3 sleep state during the wait.
As of Windows 10, though, the code after Thread.sleep() does not execute "on time" if the machine has been in S3 during the interval. It appears that the machine begins executing code at "msToWait" plus the time the machine has been in S3.
Earlier versions of Windows did not exhibit this behavior; code after Thread.sleep() waited the right amount of time, irrespective of sleep status.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
A test program and procedure were developed. The procedure is to 1) run the program, 2) cause the machine to sleep for about a minute, then 3) wake the machine and wait for the program to finish.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The Thread.sleep() will sleep for approximately the amount of ms specified.
ACTUAL -
The Thread.sleep() sleeps for the amount of ms specified plus the amount of time the machine was in S3 or other suspended state.
---------- BEGIN SOURCE ----------
import java.util.Date;
public class SleepTester {
private static int mMinutes;
private static int mDefault = 5;
public static void main(String[] args) throws Exception {
for (int iArg = 0; iArg < args.length; ++iArg) {
if (args[iArg].equals("-minutes") && (iArg + 1) < args.length) {
mMinutes = Integer.parseInt(args[++iArg]);
}
}
if (mMinutes == 0) {
mMinutes = mDefault;
System.out.println(new Date() + " Using default number of minutes: " + mDefault);
System.out.println(new Date() + " You can use \"SleepTester -minutes 10\" to have it sleep for 10 minutes, for example.");
}
System.out.println(new Date() + " Java Runtime Version: " + System.getProperty("java.runtime.version") + " JVM Version: " + System.getProperty("java.vm.version") + " Windows Version: " + System.getProperty("os.name"));
long msDelay = mMinutes * 60 * 1000;
long wakePoint = new Date().getTime() + msDelay;
System.out.println(new Date() + " The program will now wait for " + mMinutes + " minutes. Expect wrap-up at " + new Date(wakePoint));
Thread.sleep(msDelay); // If the machine goes into S3 during this interval, it should not matter, as long as it's awake when it fires.
System.out.println(new Date() + " The system has come through the Thread.sleep(" + msDelay + "). ");
long msAccuracy = Math.abs(new Date().getTime() - wakePoint);
System.out.println(new Date() + " This should be a low number: " + msAccuracy);
if (msAccuracy > 1000) System.out.println(new Date() + " This appears to be operating incorrectly...the expected sleep time has NOT been achieved.");
System.out.println(new Date() + " Program is ending.");
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Use the technique of the executable test case in a loop that checks for inaccuracies in the clock, and if found, reset the clock.
FREQUENCY : always