Pause Thread Execution

Thread Scheduling:

A processor’s time is usually time-sliced to allow multiple threads to run, with each thread using one or more time slices. A thread scheduler might suspend a running thread and move it to the ready state, executing another thread from the ready queue. Thread scheduling is specific to JVM implementation and beyond the control of an application programmer. The scheduler moves a thread from the READY state to RUNNING and vice versa, to support concurrent processing of threads.

Thread Priorities:

  1. Remember that all the threads carry normal priority when a priority is not specified.

  2. Priorities can be specified from 1 to 10. 10 being the highest, 1 being the lowest priority and 5 being the normal priority.

  3. Remember that the thread with highest priority will be given preference in execution. But there is no guarantee that it will be in running state the moment it starts.

  4. Always the currently executing thread might have the higher priority when compared to the threads in the pool who are waiting for their chance.

  5. It is the thread scheduler which decides what thread should be executed.

  6. t.setPriority() can be used to set the priorities for the threads.

  7. Remember that the priorities should be set before the threads start method is invoked.

  8. You can use the constants, MIN_PRIORITY,MAX_PRIORITY and NORM_PRIORITY for setting priorities.

1) yield() :

Theoretically, to ‘yield’ means to let go, to give up, to surrender. A yielding thread tells the virtual machine that it’s willing to let other threads be scheduled in its place. This indicates that it’s not doing something too critical. Note that it’s only a hint, though, and not guaranteed to have any effect at all.

yield() is defined as following in Thread.java.

/**
  * 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. Yield is a heuristic attempt to improve relative progression between threads that would otherwise over-utilize a CPU.
  * Its use should be combined with detailed profiling and benchmarking to ensure that it actually has the desired effect.
  */
 
public static native void yield();

Let’s list down important points from above definition:

  • Yield is a Static method and Native too.

  • Yield tells the currently executing thread to give a chance to the threads that have equal priority in the Thread Pool.

  • There is no guarantee that Yield will make the currently executing thread to runnable state immediately.

  • It can only make a thread from Ready State to Running State, not in wait or blocked state.

Example :

In below example program, I have created two threads named producer and consumer for no specific reason. Producer is set to minimum priority and consumer is set to maximum priority. I will run below code with/without commenting the line Thread.yield(). Without yield(), though the output changes sometimes, but usually first all consumer lines are printed and then all producer lines.

With using yield() method, both prints one line at a time and pass the chance to another thread, almost all the time.

package test.core.threads;
 
public class YieldExample
{
   public static void main(String[] args)
   {
      Thread producer = new Producer();
      Thread consumer = new Consumer();
       
      producer.setPriority(Thread.MIN_PRIORITY); //Min Priority
      consumer.setPriority(Thread.MAX_PRIORITY); //Max Priority
       
      producer.start();
      consumer.start();
   }
}
 
class Producer extends Thread
{
   public void run()
   {
      for (int i = 0; i < 5; i++)
      {
         System.out.println("I am Producer : Produced Item " + i);
         Thread.yield();
      }
   }
}
 
class Consumer extends Thread
{
   public void run()
   {
      for (int i = 0; i < 5; i++)
      {
         System.out.println("I am Consumer : Consumed Item " + i);
         Thread.yield();
      }
   }
}

Output of above program “without” yield() method

I am Consumer : Consumed Item 0
 I am Consumer : Consumed Item 1
 I am Consumer : Consumed Item 2
 I am Consumer : Consumed Item 3
 I am Consumer : Consumed Item 4
 I am Producer : Produced Item 0
 I am Producer : Produced Item 1
 I am Producer : Produced Item 2
 I am Producer : Produced Item 3
 I am Producer : Produced Item 4

Output of above program “with” yield() method added

I am Producer : Produced Item 0
 I am Consumer : Consumed Item 0
 I am Producer : Produced Item 1
 I am Consumer : Consumed Item 1
 I am Producer : Produced Item 2
 I am Consumer : Consumed Item 2
 I am Producer : Produced Item 3
 I am Consumer : Consumed Item 3
 I am Producer : Produced Item 4
 I am Consumer : Consumed Item 4

2) join()

java.lang.Thread class provides the join() method which allows one thread to wait until another thread completes its execution. If t is a Thread object whose thread is currently executing, then t.join(); it causes the current thread to pause its execution until thread it join completes its execution. If there are multiple threads calling the join() methods that means overloading on join allows the programmer to specify a waiting period. However, as with sleep, join is dependent on the OS for timing, so you should not assume that join will wait exactly as long as you specify. There are three overloaded join functions.

  1. join(): It will put the current thread on wait until the thread on which it is called is dead. If thread is interrupted then it will throw InterruptedException. Syntax:

    public final void join()
  2. join(long millis) :It will put the current thread on wait until the thread on which it is called is dead or wait for specified time (milliseconds). Syntax:

    public final synchronized void join(long millis)
  3. join(long millis, int nanos): It will put the current thread on wait until the thread on which it is called is dead or wait for specified time (milliseconds + nanos). Syntax:

    public final synchronized void join(long millis, int nanos)

    Example :

package com.gns.threads;

import java.util.Set;

public class TestYieldThread {
	public static void main(String[] args) {
		Thread producerThread = new Thread(new Producer(), "Producer-Thread");
		Thread consumerThread = new Thread(new Consumer(), "Consumer-Thread");
		producerThread.start();
		consumerThread.start();
		try {
			producerThread.join();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("main() execution resumed");
		Set<Thread> threadsStates = Thread.getAllStackTraces().keySet();
		for (Thread thread : threadsStates) {
			System.out.println(thread + "state-> " + thread.getState());
		}
	}
}
package com.gns.threads;

import java.util.Set;

public class Producer implements Runnable {
	@Override
	public void run() {
		for (int i = 0; i < 5; i++) {
			System.out.println("Producer producing item " + i);
		}
		Set<Thread> threadsStates = Thread.getAllStackTraces().keySet();
		for (Thread thread : threadsStates) {
			System.out.println(thread + "state-> " + thread.getState());
		}
	}

}
package com.gns.threads;

public class Consumer implements Runnable {
	@Override
	public void run() {
		for (int i = 0; i < 5; i++) {
			System.out.println("Consumer consuming item " + i);
		}

	}

}
Producer producing item 0
Consumer consuming item 0
Consumer consuming item 1
Consumer consuming item 2
Producer producing item 1
Consumer consuming item 3
Consumer consuming item 4
Producer producing item 2
Producer producing item 3
Producer producing item 4
Thread[Reference Handler,10,system]state-> WAITING
Thread[Attach Listener,5,system]state-> RUNNABLE
Thread[Producer-Thread,5,main]state-> RUNNABLE
Thread[main,5,main]state-> WAITING
Thread[Finalizer,8,system]state-> WAITING
Thread[Signal Dispatcher,9,system]state-> RUNNABLE
main() execution resumed
Thread[Reference Handler,10,system]state-> WAITING
Thread[Attach Listener,5,system]state-> RUNNABLE
Thread[main,5,main]state-> RUNNABLE
Thread[Finalizer,8,system]state-> WAITING
Thread[Signal Dispatcher,9,system]state-> RUNNABLE

As we can see , main() thread was sent to waiting state when producerThread.join() was called.Hence after the completion of producerThread main() thread resumed its execution.

3) sleep()

This method causes the currently executing thread to sleep for the specified number of milliseconds, subject to the precision and accuracy of system timers and schedulers. Syntax:

//  sleep for the specified number of milliseconds
public static void sleep(long millis) throws InterruptedException

//sleep for the specified number of milliseconds plus nano seconds
public static void sleep(long millis, int nanos) 
                         throws InterruptedException
// Java program to illustrate 
// sleep() method in Java 
import java.lang.*; 

public class SleepDemo implements Runnable 
{ 
	Thread t; 
	public void run() 
	{ 
		for (int i = 0; i < 4; i++) 
		{ 
			System.out.println(Thread.currentThread().getName() 
												+ " " + i); 
			try
			{ 
				// thread to sleep for 1000 milliseconds 
				Thread.sleep(1000); 
			} 

			catch (Exception e) 
			{ 
				System.out.println(e); 
			} 
		} 
	} 

	public static void main(String[] args) throws Exception 
	{ 
		Thread t = new Thread(new SleepDemo()); 

		// call run() function 
		t.start(); 

		Thread t2 = new Thread(new SleepDemo()); 

		// call run() function 
		t2.start(); 
	} 
}

Output:

Thread-0  0
Thread-1  0
Thread-0  1
Thread-1  1
Thread-0  2
Thread-1  2
Thread-0  3
Thread-1  3

Java Thread Sleep important points

  1. It always pause the current thread execution.

  2. The actual time thread sleeps before waking up and start execution depends on system timers and schedulers. For a quiet system, the actual time for sleep is near to the specified sleep time but for a busy system it will be little bit more.

  3. Thread sleep doesn’t lose any monitors or locks current thread has acquired.

  4. Any other thread can interrupt the current thread in sleep, in that case InterruptedException is thrown.

How Thread Sleep Works

Thread.sleep() interacts with the thread scheduler to put the current thread in wait state for specified period of time. Once the wait time is over, thread state is changed to runnable state and wait for the CPU for further execution. So the actual time that current thread sleep depends on the thread scheduler that is part of operating system.

Last updated