I have observed that Thead.sleep(long) waits for too long if the system time changes backwards on linux systems with an up to date kernel.
Can anybody confirm this?
This is what I tested:
All combinations of:
JRE 1.7.0_25 64 bit and JRE 1.7.0_11 64 bit
OpenSUSE 12.3 (kernel 3.7.10-1.16-default) and Ubuntu 13.04 (kernel 3.8.0-19.29)
I started a java test program listed below and changed the system time back (using date +%T -s "10:50:00").
The test program prints out the current time once a second. When setting the system time back the test program stops until the system time reached the old time so Thread.sleep(1000) waits much more than one second.
Output:
Tue Sep 03 09:44:48 UTC 2013
Tue Sep 03 09:44:49 UTC 2013
Tue Sep 03 09:44:50 UTC 2013
=> Time change with "date +%T -s "09:44:00"
Tue Sep 03 09:44:51 UTC 2013
Tue Sep 03 09:44:52 UTC 2013
...
Expected:
Tue Sep 03 09:44:48 UTC 2013
Tue Sep 03 09:44:49 UTC 2013
Tue Sep 03 09:44:50 UTC 2013
=> Time change with "date +%T -s "09:44:00"
Tue Sep 03 09:44:00 UTC 2013
Tue Sep 03 09:44:01 UTC 2013
...
The same test program works fine with kernel 2.6.31.14-0.8-default so I guess there has been a change in the kernel which has not been updated in the JRE?
There have been similar bugs but I thought they have been solved (e.g.: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6900441) .
Testprogram:
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimeZone;
public class SleepTest
{
private TimeZone defaultTimeZone = null;
private final String TIME_FORMAT = " HH:mm:ss ";
private SimpleDateFormat timeFormat = null;
SleepTest()
{
this.defaultTimeZone = TimeZone.getDefault();
this.timeFormat = new SimpleDateFormat(this.TIME_FORMAT);
this.timeFormat.setTimeZone(this.defaultTimeZone);
System.out.println(Calendar.getInstance(this.defaultTimeZone).getTime());
for (;;)
{
try
{
Thread.sleep(1000);
System.out.println(Calendar.getInstance(this.defaultTimeZone).getTime());
}
catch (Exception e)
{
System.out.println(Calendar.getInstance(this.defaultTimeZone).getTime());
System.out.println(e);
}
}
}
public static void main(String[] args)
{
new SleepTest();
try
{
Thread.sleep(1000000000);
}
catch (Exception e)
{
}
}
}