How to Kill a Java Thread

1. Introduction

In this brief article, we’ll cover stopping a Thread in Java – which is not that simple since the Thread.stop() method is deprecated.

As explained in this update from Oracle, stop() can lead to monitored objects being corrupted.

2. Using a Flag

Let’s start with a class that creates and starts a thread. This task won’t end on its own, so we need some way of stopping that thread.

We’ll use an atomic flag for that:

public class ControlSubThread implements Runnable {

    private Thread worker;
    private final AtomicBoolean running = new AtomicBoolean(false);
    private int interval;

    public ControlSubThread(int sleepInterval) {
        interval = sleepInterval;
    }
 
    public void start() {
        worker = new Thread(this);
        worker.start();
    }
 
    public void stop() {
        running.set(false);
    }

    public void run() { 
        running.set(true);
        while (running.get()) {
            try { 
                Thread.sleep(interval); 
            } catch (InterruptedException e){ 
                Thread.currentThread().interrupt();
                System.out.println(
                  "Thread was interrupted, Failed to complete operation");
            }
            // do something here 
         } 
    } 
}

Rather than having a while loop evaluating a constant true, we’re using an AtomicBoolean and now we can start/stop execution by setting it to true/false.

As explained in our introduction to Atomic Variables, using an AtomicBoolean prevents conflicts in setting and checking the variable from different threads.

3. Interrupting a Thread

What happens when sleep() is set to a long interval, or if we’re waiting for a lock that might never be released?

We face the risk of blocking for a long period or never terminating cleanly.

We can create the interrupt() for these situations, let’s add a few methods and a new flag to the class:

public class ControlSubThread implements Runnable {

    private Thread worker;
    private AtomicBoolean running = new AtomicBoolean(false);
    private int interval;

    // ...

    public void interrupt() {
        running.set(false);
        worker.interrupt();
    }

    boolean isRunning() {
        return running.get();
    }

    boolean isStopped() {
        return stopped.get();
    }

    public void run() {
        running.set(true);
        stopped.set(false);
        while (running.get()) {
            try {
                Thread.sleep(interval);
            } catch (InterruptedException e){
                Thread.currentThread().interrupt();
                System.out.println(
                  "Thread was interrupted, Failed to complete operation");
            }
            // do something
        }
        stopped.set(true);
    }
}

We’ve added an interrupt() method that sets our running flag to false and calls the worker thread’s interrupt() method.

If the thread is sleeping when this is called, sleep() will exit with an InterruptedException, as would any other blocking call.

This returns the thread to the loop, and it will exit since running is false.

4. Conclusion

In this quick tutorial, we looked at how to use an atomic variable, optionally combined with a call to interrupt(), to cleanly shut down a thread. This is definitely preferable to calling the deprecated stop() method and risking locking forever and memory corruption.

As always, the full source code is available over on GitHub.

Related posts:

How to Change the Default Port in Spring Boot
Java Program to Implement Rolling Hash
How to Add a Single Element to a Stream
Mockito and JUnit 5 – Using ExtendWith
Case-Insensitive String Matching in Java
Java Program to Check Whether an Undirected Graph Contains a Eulerian Cycle
Intro to Inversion of Control and Dependency Injection with Spring
ArrayList trong java
Introduction to the Java NIO Selector
Spring Boot - Tomcat Deployment
A Guide to Iterator in Java
Java Program to Implement Bubble Sort
Hướng dẫn Java Design Pattern – Template Method
Java Program to Implement PriorityBlockingQueue API
Rest Web service: Filter và Interceptor với Jersey 2.x (P2)
Spring MVC Content Negotiation
Java Program to Implement LinkedBlockingDeque API
Java Program to Implement CopyOnWriteArrayList API
Java Program to Check the Connectivity of Graph Using DFS
Các nguyên lý thiết kế hướng đối tượng – SOLID
Java Program to Implement Traveling Salesman Problem using Nearest neighbour Algorithm
Convert XML to JSON Using Jackson
Spring Boot - Exception Handling
Java Program to Find the Peak Element of an Array O(n) time (Naive Method)
Custom Exception trong Java
REST Web service: HTTP Status Code và xử lý ngoại lệ RESTful web service với Jersey 2.x
Java Program to Solve Travelling Salesman Problem for Unweighted Graph
Lập trình đa luồng với Callable và Future trong Java
Performance Difference Between save() and saveAll() in Spring Data
Java Program to Implement Stack using Two Queues
Merging Two Maps with Java 8
Spring Boot - CORS Support