A thread is automatically destroyed when the run() method has completed. But it might be required to kill/stop a thread before it has completed its life cycle. Previously, methods suspend(), resume() and stop() were used to manage the execution of threads. But these methods were deprecated by Java 2 because they could result in system failures. Modern ways to suspend/stop a thread are by using a boolean flag and Thread.interrupt() method.
- Using a boolean flag: We can define a boolean variable which is used for stopping/killing threads say ‘exit’. Whenever we want to stop a thread, the ‘exit’ variable will be set to true.
Java
// Java program to illustrate // stopping a thread using boolean flag class MyThread implements Runnable { // to stop the thread private boolean exit; private String name; Thread t; MyThread(String threadname) { name = threadname; t = new Thread( this , name); System.out.println( "New thread: " + t); exit = false ; t.start(); // Starting the thread } // execution of thread starts from run() method public void run() { int i = 0 ; while (!exit) { System.out.println(name + ": " + i); i++; try { Thread.sleep( 100 ); } catch (InterruptedException e) { System.out.println( "Caught:" + e); } } System.out.println(name + " Stopped." ); } // for stopping the thread public void stop() { exit = true ; } } // Main class public class Main { public static void main(String args[]) { // creating two objects t1 & t2 of MyThread MyThread t1 = new MyThread( "First thread" ); MyThread t2 = new MyThread( "Second thread" ); try { Thread.sleep( 500 ); t1.stop(); // stopping thread t1 t2.stop(); // stopping thread t2 Thread.sleep( 500 ); } catch (InterruptedException e) { System.out.println( "Caught:" + e); } System.out.println( "Exiting the main Thread" ); } } |
New thread: Thread[First thread, 5, main] New thread: Thread[Second thread, 5, main] First thread: 0 Second thread: 0 First thread: 1 Second thread: 1 First thread: 2 Second thread: 2 First thread: 3 Second thread: 3 First thread: 4 Second thread: 4 First thread: 5 Second thread Stopped. First thread Stopped. Exiting the main Thread
Note: The output may vary every time.
By using a flag we can stop a thread whenever we want to and we can prevent unwanted run-time errors.
- Using a volatile boolean flag: We can also use a volatile boolean flag to make our code thread safe. A volatile variable is directly stored in the main memory so that threads cannot have locally cached values of it. A situation may arise when more than one threads are accessing the same variable and the changes made by one might not be visible to other threads. In such a situation, we can use a volatile boolean flag.
Let’s consider the code below where we use a non-volatile boolean flag:
Java
// Java program to illustrate non-volatile boolean flag public class Main { // static used here // because a non-static variable // cannot be referenced // from a static context // exit variable to stop both // the main and inside threads static boolean exit = false ; public static void main(String[] args) { System.out.println( "started main thread.." ); // a thread inside main thread new Thread() { public void run() { System.out.println( "started inside thread.." ); // inside thread caches the value of exit, // so changes made to exit are not visible here while (!exit) // will run infinitely { } // this will not be printed. System.out.println( "exiting inside thread.." ); } }.start(); try { Thread.sleep( 500 ); } catch (InterruptedException e) { System.out.println( "Caught :" + e); } // so that we can stop the threads exit = true ; System.out.println( "exiting main thread.." ); } } |
Runtime Errors:
Time Limit Exceeded
Output:
started main thread.. started inside thread.. exiting main thread..
Note: The above code runs into an infinite loop and will give run-time error.
The output above shows that the inside thread is never stopped. This happens because the change made to ‘exit’ variable in the main thread is not visible to the inside thread. This is so because the inside thread locally caches the value of exit. To prevent this from happening we can use a volatile variable. The code below illustrates it.
Java
// Java program to illustrate volatile boolean flag public class Main { // static used here because // a non-static variable cannot be referenced // from a static context // exit variable to stop both // the main and inside threads static volatile boolean exit = false ; public static void main(String[] args) { System.out.println( "started main thread.." ); // a thread inside main thread new Thread() { public void run() { // changes made to exit // in main thread are visible here System.out.println( "started inside thread.." ); // will not run infinitely while (!exit) { } // this will be printed System.out.println( "exiting inside thread.." ); } }.start(); try { Thread.sleep( 500 ); } catch (InterruptedException e) { System.out.println( "Caught :" + e); } // so that we can stop the threads exit = true ; System.out.println( "exiting main thread.." ); } } |
started main thread.. started inside thread.. exiting main thread.. exiting inside thread..
The output above shows that when we use a volatile boolean flag, we do not run into infinite loops. This is because the volatile variable directly stored in the main memory. In other words, changes made by one thread are visible to other threads. Thus using volatile makes our code, thread safe.
- Using Thread.interrupt() method: Whenever an interrupt has been sent to a thread, it should stop whatever task it is performing. It is very likely that whenever the thread receives an interrupt, it is to be terminated. This action can be done by using the interrupt() method. Whenever Thread.interrupt() is called, it sets a flag known as the interrupt status to true. This means that the thread has to stop performing further execution. The default value of this flag is false.
Java
// Java program to illustrate // stopping a thread // using the interrupt() method class MyThread implements Runnable { Thread t; MyThread() { t = new Thread( this ); System.out.println( "New thread: " + t); t.start(); // Starting the thread } // execution of thread starts from run() method public void run() { while (!Thread.interrupted()) { System.out.println( "Thread is running" ); } System.out.println( "Thread has stopped." ); } } // Main class public class Main { public static void main(String args[]) { // creating objects t1 of MyThread MyThread t1 = new MyThread(); try { Thread.sleep( 1 ); // t1 is an object of MyThread // which has an object t // which is of type Thread t1.t.interrupt(); Thread.sleep( 5 ); } catch (InterruptedException e) { System.out.println( "Caught:" + e); } System.out.println( "Exiting the main Thread" ); } } |
New thread: Thread[Thread-0, 5, main] Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread is running Thread has stopped. Exiting the main Thread
Note: The output may vary every time.