JDK-5041555 : Thread.sleep sleeps extra 10ms. (Thread.sleep(1000) -> 1010ms).
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 1.4.2
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: linux
  • CPU: x86
  • Submitted: 2004-05-03
  • Updated: 2004-05-05
  • Resolved: 2004-05-05
Related Reports
Duplicate :  
Description

Name: jl125535			Date: 05/03/2004


FULL PRODUCT VERSION :
java version "1.4.2_04"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_04-b05)
Java HotSpot(TM) Client VM (build 1.4.2_04-b05, mixed mode)

Does NOT occur on:
java version "1.3.1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1-b24)
Java HotSpot(TM) Client VM (build 1.3.1-b24, mixed mode)


FULL OS VERSION :
Fedora core 1 (Linux) (i686 athlon i386 GNU/Linux)

Does NOT occur on: SunOS (5.8 Generic_108528-27 sun4u sparc SUNW,Sun-Blade-1000)


A DESCRIPTION OF THE PROBLEM :
Thread.sleep sleeps for an extra 10ms. For example Thread.sleep(1000) sleeps 1010ms.
And this is the case with all sleeptimes except 0.

The resolution of sleep on my configuration is 10ms. 31-39ms are rounded to 40ms, 101-109ms are rounded to 110ms etc.

I also tried the program with sleeptime being 91ms, which is rounded up to 100ms -> sleeps for 110ms.

System.currentTimeMillis() seems to be accurate since I get everything starting from a single sleep(10) measured (1x10ms results ~20ms, 1x20ms results ~30ms etc). Measuring loops without sleep I get around 0.
The problem can't be in System.currentTimeMillis() because if it gave an extra 10ms, I would be getting 100*100m -> 10010, not 11000.

I tried on the "Does NOT occur" configuration shown above and everything worked as presumed
(100ms * 100 -> 10000ms).


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the program with different sleeptimes.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
You should receive approximation of the sleeptime used multiplied with 100.
Sleep(100) -> 10 000
Sleep(1000) -> 100 000
ACTUAL -
But I receive:
Sleep(100) -> 11 000
Sleep(1000) -> 101 000

And by calculating only single sleepcalls:
Sleep(30) -> 40
Sleep(100) -> 110
Sleep(1000) -> 1010

Sleep(0) -> 0

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
public class Test
{
  public static void main(String[] args)
  {
    long start = System.currentTimeMillis();
    for(int i = 0; i < 100; i++) {
      try {
        Thread.sleep(100);
      } catch( InterruptedException e) {}
  }
  long stop = System.currentTimeMillis();
  System.out.println("Time: " + (stop - start));
  }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Obviously reduce 10ms from each sleepcall (with at least 10ms as sleeptime).
(Incident Review ID: 244625) 
======================================================================

Comments
PUBLIC COMMENTS The test case supplied with this bug demonstrates the effect of thread (or underlying process) scheduling. Documentation updates will clarify this implementation-defined behavior. The contract for Thread.sleep is that the delay will be as long as specified but it is simply impossible to mandate the actual delay and currently too expensive to make it more precise.
10-06-2004

EVALUATION This is not a bug, this is expected behavior. See item #51 in Bloch's book "Effective Java" (don't depend on the thread scheduler). Depending on the operating system type, load factor and many other variables, the delay specified for Thread.sleep() will be the time requested or "some increment longer". It is very frequently one scheduler quantum longer than requested (10ms is a common time period but it varies). The J2SE 1.5 release notes will contain a clarification of Thread.sleep() behavior and a request has been made to consider a change to the javadoc the two versions of this method to make it clear that the platform causes the actual delay to be "for at least the specified number of..." That is, the interface contract is to delay for no shorter time than specified but when the thread begins executing again is platform-specific and ultimately unknowable. On some operating system platforms a higher precision timing is possible by putting a program into a special "mode" but this creates other problems with increased overhead both in user space and in the OS kernel and sometimes interacts with the performance of multithreaded applications in undesirable ways. Other approaches to get higher precision may be explored in the future. ###@###.### 2004-05-05
05-05-2004