Difference between yield() and sleep() methods in Java is a very frequently asked Java multi-threading interview question. As both of the methods are related to pausing the currently executing thread so it does create some confusion. In this post let's see the differences between yield() and sleep() methods to have clarity over the usage.
Please keep in mind that both yield() and sleep() are static methods of the Java Thread class. When called both of these methods will work on the currently executing thread, not on any particular thread.
As example if there are three threads running T1, T2 and T3. Calling Thread.sleep() or Thread.yield() will work on whichever thread is currently executing. You can't say T1.sleep() or T3.yield() to put T1 thread to sleep or T3 thread to yield.
yield() method in Java
Calling yield() method is a hint to the scheduler that the current thread is willing to yield its current use of a processor. The scheduler is free to ignore this hint. If the hint is not ignored then the executing thread is suspended and the CPU is given to some other runnable thread.
The suspended thread will wait until the CPU becomes available again. Technically, in process scheduler's terminology, the executing thread is put back into the ready queue of the processor and waits for its next turn.
According to JavaDOC-
http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#yield--
It is rarely appropriate to use this method. It may be useful for debugging or testing purposes, where it may help to reproduce bugs due to
race conditions. It may also be useful when designing concurrency control constructs such as the ones in the java.util.concurrent.locks
package.
Java yield() method example
In this example code three threads are spawned. In the run method there is a loop which runs 3 times printing value of variable i. Currently executing thread is asked to yield when value of i is 1, that gives another thread to start execution.
public class YieldDemo { public static void main(String[] args) { YieldClass yc = new YieldClass(); Thread thread1 = new Thread(yc, "Thread1"); Thread thread2 = new Thread(yc, "Thread2"); Thread thread3 = new Thread(yc, "Thread3"); thread1.start(); thread2.start(); thread3.start(); try { thread1.join(); thread2.join(); thread3.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("Execution finished"); } } class YieldClass implements Runnable{ @Override public void run() { System.out.println("Executing run for Thread - " + Thread.currentThread().getName()); for(int i = 0; i < 3; i++){ System.out.println("i " + i + "Thread- " + Thread.currentThread().getName()); if(i == 1){ System.out.println("Yielding thread : "+ Thread.currentThread().getName()); Thread.yield(); } } } }
Output
Executing run for Thread - Thread1 Executing run for Thread - Thread2 i 0Thread- Thread1 i 0Thread- Thread2 i 1Thread- Thread1 i 1Thread- Thread2 Yielding thread : Thread1 Yielding thread : Thread2 Executing run for Thread - Thread3 i 0Thread- Thread3 i 1Thread- Thread3 Yielding thread : Thread3 i 2Thread- Thread1 i 2Thread- Thread2 i 2Thread- Thread3 Execution finished
It can be seen from the output how Thread 1 and Thread 2 are interleaving and they both are printing value of i as 0 and 1. At that point yield method is called that gives a chance to Thread 3 to start its execution.
sleep() method in Java
sleep() method causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds.
Java sleep() method example
In this example code three threads are spawned. In the run method there is a loop which runs 3 times printing value of variable i. sleep() method is called on the currently executing thread when value of i is 1 with argument as 100, which causes the current thread to sleep for 100 milliseconds.
public class SleepDemo { public static void main(String[] args) { SleepClass yc = new SleepClass(); Thread thread1 = new Thread(yc, "Thread1"); Thread thread2 = new Thread(yc, "Thread2"); Thread thread3 = new Thread(yc, "Thread3"); thread1.start(); thread2.start(); thread3.start(); try { thread1.join(); thread2.join(); thread3.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("Execution finished"); } } class SleepClass implements Runnable{ @Override public void run() { System.out.println("Executing run for Thread - " + Thread.currentThread().getName()); //synchronized(this){ for(int i = 0; i < 3; i++){ System.out.println("i " + i + "Thread- " + Thread.currentThread().getName()); if(i == 1){ System.out.println("Going to sleep thread : "+ Thread.currentThread().getName()); try { Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } //} } }
Output
Executing run for Thread - Thread1 Executing run for Thread - Thread2 i 0Thread- Thread1 i 0Thread- Thread2 i 1Thread- Thread1 i 1Thread- Thread2 Going to sleep thread : Thread1 Going to sleep thread : Thread2 Executing run for Thread - Thread3 i 0Thread- Thread3 i 1Thread- Thread3 Going to sleep thread : Thread3 i 2Thread- Thread2 i 2Thread- Thread1 i 2Thread- Thread3 Execution finished
yield() Vs sleep() in Java
Based on these descriptions of sleep and yield one of the difference between yield() and sleep() methods is that a thread which has yielded may become eligible to run again as soon as it has yielded if there is no other thread with the same or more thread priority.
Where as in case of sleep() the thread will definitely go to sleep for the specified time (unless it is interrupted) and in the meantime another thread (of less or more priority) can start its execution.
Calling yield() and sleep() methods from synchronized context
Another important point to note here is, if yield() or sleep() method is invoked on the current thread, the current thread doesn't have to give up the locks it is holding if called from the synchronized context, as in the case with wait method.
yield() with synchronized example
Here I am using the same code as above just kept the for loop inside a synchronized block.
public class YieldDemo { public static void main(String[] args) { YieldClass yc = new YieldClass(); Thread thread1 = new Thread(yc, "Thread1"); Thread thread2 = new Thread(yc, "Thread2"); Thread thread3 = new Thread(yc, "Thread3"); thread1.start(); thread2.start(); thread3.start(); try { thread1.join(); thread2.join(); thread3.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("Execution finished"); } } class YieldClass implements Runnable{ @Override public void run() { System.out.println("Executing run for Thread - " + Thread.currentThread().getName()); synchronized(this){ for(int i = 0; i < 3; i++){ System.out.println("i " + i + "Thread- " + Thread.currentThread().getName()); if(i == 1){ System.out.println("Yielding thread : "+ Thread.currentThread().getName()); Thread.yield(); } } } } }
Output
Executing run for Thread - Thread1 Executing run for Thread - Thread2 i 0Thread- Thread1 i 1Thread- Thread1 Yielding thread : Thread1 Executing run for Thread - Thread3 i 2Thread- Thread1 i 0Thread- Thread3 i 1Thread- Thread3 Yielding thread : Thread3 i 2Thread- Thread3 i 0Thread- Thread2 i 1Thread- Thread2 Yielding thread : Thread2 i 2Thread- Thread2 Execution finished
It can be seen how "Executing run for Thread" message is printed for both Thread-1 and Thread-2 but only Thread-1 enters the synchronized block. Thread-1 yields after value of i becomes 1. But again Thread-1 is executed as it is the thread currently holding the lock. Only after it releases the lock another thread starts its execution.
sleep() with synchronized example
public class SleepDemo { public static void main(String[] args) { SleepClass yc = new SleepClass(); Thread thread1 = new Thread(yc, "Thread1"); Thread thread2 = new Thread(yc, "Thread2"); Thread thread3 = new Thread(yc, "Thread3"); thread1.start(); thread2.start(); thread3.start(); try { thread1.join(); thread2.join(); thread3.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("Execution finished"); } } class SleepClass implements Runnable{ @Override public void run() { System.out.println("Executing run for Thread - " + Thread.currentThread().getName()); synchronized(this){ for(int i = 0; i < 3; i++){ System.out.println("i " + i + "Thread- " + Thread.currentThread().getName()); if(i == 1){ System.out.println("Going to sleep thread : "+ Thread.currentThread().getName()); try { Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } }
Output
Executing run for Thread - Thread1 i 0Thread- Thread1 i 1Thread- Thread1 Going to sleep thread : Thread1 Executing run for Thread - Thread3 Executing run for Thread - Thread2 i 2Thread- Thread1 i 0Thread- Thread2 i 1Thread- Thread2 Going to sleep thread : Thread2 i 2Thread- Thread2 i 0Thread- Thread3 i 1Thread- Thread3 Going to sleep thread : Thread3 i 2Thread- Thread3 Execution finished
That's all for this topic Difference Between yield And sleep in Java Multi-Threading. If you have any doubt or any suggestions to make please drop a comment. Thanks!
Related Topics
You may also like-
No comments:
Post a Comment