Wednesday, November 3, 2021

Difference Between yield And sleep in Java Multi-Threading

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

  1. Creating a Thread in Java
  2. Thread States (Thread Life Cycle) in Java Multi-Threading
  3. Inter-thread Communication Using wait(), notify() And notifyAll() in Java
  4. Java ThreadLocal Class With Examples
  5. Volatile Keyword in Java With Examples

You may also like-

  1. Abstraction in Java
  2. CopyOnWriteArrayList in Java With Examples
  3. Difference Between StackOverflowError and OutOfMemoryError in Java
  4. Interface Static Methods in Java
  5. Fail-Fast Vs Fail-Safe Iterator in Java
  6. Java Lambda Expression And Variable Scope
  7. Java Program to Find First Non-Repeated Character in a Given String
  8. Just In Time Compiler (JIT) in Java

No comments:

Post a Comment