Monday, 13 July 2015

Difference between yield and sleep - Java Multi-threading

Difference between yield and sleep is a very frequently asked Java multi-threading 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 these 2 methods to have clarity over the usage.

Please keep in mind that both yield() and sleep() are static methods of the 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

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.

Yield example code

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

sleep() method causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds.

Sleep Example code

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

Difference between yield and sleep

Based on these descriptions of sleep and yield one of the the difference between these 2 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.

Same example with sleep

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. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. What if run() method called directly instead of start() method
  2. Can we start the same thread twice in Java
  3. Creating thread in Java
  4. Synchronization in Java multithreading
  5. Race condition in Java multi-threading
  6. Java Multi-threading interview questions

You may also like -

No comments:

Post a Comment