Wednesday, May 14, 2008

Difference between sleep and wait


Thread.sleep(long milliseconds): sends the current thread into Non-Runnable state for the specified amount of time. But, this doesn’t cause the thread to loose ownership of the acquired monitors. So, if the current thread is into a synchronized block/method, then no other thread will be able to enter that block/method.

This method throws ‘InterruptedException’ if another thread interrupts it.

There is another variant of the ‘sleep()’ method as well where it accepts two arguments – one, long milliseconds, and second, int nanoseconds. Evidently, it causes the current thread to sleep for the specified number of milliseconds plus the specified number of nanoseconds. The second argument ‘int nanoseconds’ can acquire a value of the range 0-999999.

Another noticeable difference between the two variants is that sleep(long milliseconds, int nanoseconds) throws an IllegalArgumentException if either the value of milliseconds is negative or the value of nanoseconds is not in the range 0-999999. As is the case with the first variant, it throws InterruptedException is another thread interrupts it.

Common Error: both these methods are static, so even if you try to call ‘t.sleep(…)’ on a different thread, it’ll be called on the current thread only and not on the ‘t’ thread. In fact, one should avoid calling any static method on an object reference.

wait() method: There are three variants of this method in the ‘Object’ class:-
public final void wait(long timeout)
public final void wait(long timeout, int nanoseconds)
public final void wait()


All the three methods throw InterruptedException & IllegalMonitorStateException. The first two may also throw IllegalArgumentException.

The wait() method also sends the current thread into Non-Runnable state like the sleep() method. But, the difference between the two is that in case of ‘wait()’ the locks are released before going into Non-Runnable state. Another apparent difference is that ‘wait()’ is an instance method, while sleep() is a static method. The method ‘wait()’ should be called for an object only when the current thread has already acquired lock for that object. This causes the current thread to wait either another thread invokes the ‘notify()’ method or the ‘notifyAll()’ method for this object, or a specified amount of time has elapsed and after that the thread starts participating in thread scheduling process to acquire the monitor of the object to proceed further.

The wait() method causes the current thread to place itself in the wait set for this object and then to relinquish any and all synchronization claims on this object. After the execution of this method invocation, the thread becomes disabled for any scheduling purposes and lies dormant until one of the following things happen:-

  • Any other thread invokes ‘notify()’ method this object and the thread under consideration is arbitrarily chosen as the thread to be awakened.
  • Any other thread invokes ‘notifyAll()’ for this object.
  • Any other thread interrupts the thread under consideration.
  • The specified amount of time has elapsed (in case first two variants of wait() are used)
After any of the four above mentioned events happens, the thread is removed from the wait set for this object and re-enabled for thread scheduling. It’ll compete for the rights to synchronize on the object in an usual manner and it’ll keep doing this until it acquires control on the object and gains all the synchronization claims on the object, which it had acquired at the time of ‘wait()’ invocation. This means that after the return from wait() method, the synchronization state of object and of the thread will be exactly the same as it was before the wait() invocation.



Share/Save/Bookmark


1 comment:

javin paul said...

while using wait() and notify() method in Java Its important to understand that wait() should be called in a loop if multiple thread can wait on same condition because when threads gets notified there is no guarantee which thread will get lock and return from wait method. so if suppose two threads A and B are waiting on a condition and receives notification then both try to get lock , luckily A got lock and executed and made the condition false again but if thread B doesn't check the condition again after getting lock (which is why we need to check condition in loop) it will run even if it supposed to wait. So its important to recheck the condition after getting lock and wait again if condition is false again.

JP
Why wait() and notify() method must be called from synchronized context