Bits of Knowledge: Properly Terminating a Java Thread

Bits of Knowledge: Properly Terminating a Java Thread

Introduction

When working with multi-threaded Java application, it is generally a good practice to ensure that the threads you created will be properly terminated. Not doing so might clog your system resources because not all threads are automatically terminated when the application is closed.

This is not a problem with threads that has a single task to perform. These threads can just do their job and properly cleanup after themselves.

new Thread(() -> Files.copy(source, destination), "copy-file-thread")
    .start();
After finishing the copy operation the thread copy-file-thread will be terminated.

But how about threads that are supposed to run indefinitely? How do we tell it to stop running, and it's time to go?

new Thread(() -> {
    while (true) { // infinite loop
        var uploads = checkForNewUploads();
        processUploads(uploads);
    }
}, "upload-watcher-thread").start();
Thread with an infinite loop will not terminate unless the loop breaks. But how?

Remember that Thread.stop() method is not an option. This method is deprecated since Java 1.2 because of being unsafe. The .stop() method will force terminate a thread whatever it is doing at the time the method is called – whether it is safe or not.

Thread Interrupted Status

A good way to stop a thread without using Thread.stop() is to interrupt it. This is done by calling the Thread.interrupt() method.

Unlike stopping the thread, interrupt will only flag the thread as interrupted. The method run by the thread will have to handle the .interrupted() flag to properly respond to the interruption. This way, the thread can do whatever it needs to do to ensure that it will terminate cleanly.

var uploadWatcherThread = new Thread(() -> {
    do {
        var uploads = checkForNewUploads();
        processUploads(uploads);
    } while (!Thread.interrupted()); // interrupted() method used as loop sentinel
}, "upload-watcher-thread");
uploadWatcherThread.start();
Notice that the Thread object is assigned to a variable. This is to enable us to refer to that thread to interrupt it.
// somewhere else in the code base...
uploadWatcherThread.interrupt();
Since we have the reference to the thread we started, we can just call the .interrupt() method to flag its interrupted status.

After running the uploadWatcherThread.interrupt() from the example above, the loop will properly end due to the condition !Thread.interrupted() not satisfied anymore. Now that the loop has ended, all the code needed to run has been completed, too. This will properly terminate the thread.

We need to keep in mind that calling the method .interrupted() will clear the interrupted status of that thread. Meaning, when you call the method .interrupted() twice in the same thread consecutively, the 2nd call will return false.

Show Comments