Different Ways to Kill a Thread in Java

There is no official method to kill a thread in Java. Stopping a thread is entirely managed by the JVM. Although Java provides several ways to manage the thread lifecycle such as a start(), sleep(), stop() (deprecated in Java 1.1), etc. but does not provide any method to kill a thread and free the resources cleanly.

Oracle specified the reason for deprecating the stop() method as It is inherently unsafe. Stopping a thread causes it to unlock all its locked monitors.

1. Two Ways to Kill a Thread

Effectively, we can only signal the thread to stop itself and let the thread clean up the resources and terminate itself. In Java, we can send a signal to a thread in two ways:

  • By periodically checking a boolean flag
  • By interrupting the thread using Thread.interrupt() method

Let us learn about both methods:

2. By Checking a Flag

In this method, we check a boolean flag periodically, or after every step in the task. Initially, the flag is set to false. To stop the thread, set the flag to true. Inside the thread, when the code checks the flag’s value to true, it destroys itself gracefully and returns.

Note that in this design, generally, there are two threads. One thread sets the flag value to true, and another thread checks the flag value. To ensure that both threads see the same value all the time, we must make the flag variable volatile. Or we can use AtomicBoolean class that supports atomic operations on an underlying volatile boolean variable.

public class CustomTask implements Runnable {

  private volatile boolean flag = false;
  private Thread worker;

  public void start() {
    worker = new Thread(this);
    worker.start();
  }

  public void stop() {
    flag = true;
  }

  @Override
  public void run() {
    while (!flag) {
      try {
        Thread.sleep(500);
        System.out.println(Thread.currentThread().getName() + " Running...");
      } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        System.out.println("Thread was interrupted," + e.getMessage());
      }
    }
    System.out.println(Thread.currentThread().getName() + " Stopped");
    return;
  }
}

Let us test this design by creating two threads and stopping them.

CustomTask task1 = new CustomTask();
CustomTask task2 = new CustomTask();

task1.start();
task2.start();

try {
  Thread.sleep(1000);

  task1.stop();
  task2.stop();
} catch (InterruptedException e) {
  System.out.println("Caught:" + e);
}
Thread-0 Running...
Thread-1 Running...
Thread-1 Running...
Thread-0 Running...

Thread-1 Stopped
Thread-0 Stopped

3. By Interrupting the Thread

This method is also very similar to the previous approach of using a flag. The only difference is that we will interrupt the thread instead of setting the flag to false.

So inside the thread, we will keep checking the thread’s interrupt status, and when the thread is interrupted, we will stop the thread gracefully. To check the status of the interrupted thread, we can use the Thread.isInterrupted() method. It returns either true or false based on the thread’s interrupt status.

public class CustomTaskV2 implements Runnable {
  private Thread worker;

  public void start() {
    worker = new Thread(this);
    worker.start();
  }

  public void interrupt() {
    worker.interrupt();
  }

  @Override
  public void run() {
    while (!Thread.currentThread().isInterrupted()) {
      try {
        Thread.sleep(500);
        System.out.println(Thread.currentThread().getName() + " Running...");
      } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        System.out.println("Thread was interrupted with reason : " + e.getMessage());
      }
    }
    System.out.println(Thread.currentThread().getName() + " Stopped");
    return;
  }
}

Interestingly, the code to test this design is similar to the previous one. Only the method call to thread.interrupt() is additional.

CustomTaskV2 task1 = new CustomTaskV2();
CustomTaskV2 task2 = new CustomTaskV2();

task1.start();
task2.start();

try {
  Thread.sleep(1100);isInterrupted
  task1.interrupt();
  task2.interrupt();
} catch (InterruptedException e) {
  System.out.println("Caught:" + e);
}
Thread-0 Running...
Thread-1 Running...
Thread-1 Running...
Thread-0 Running...
Thread was interrupted with reason : sleep interrupted
Thread was interrupted with reason : sleep interrupted
Thread-0 Stopped
Thread-1 Stopped

4. Conclusion

This tutorial taught us to kill a running thread in Java using custom solutions. Even though the boolean flag solution is very good, it may not give the desired result for long-running tasks where the thread is waiting most of the time.

Sending an interrupt is a much better approach to stop a long-waiting thread.

Happy Learning !!

Source Code on Github

Leave a Reply

0 Comments
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions, and frequently asked interview questions.