Monday, July 26, 2021

How to stop a thread in Java? Example

Today we're going to learn about how to stop a thread in Java. It's easy to start a thread in Java because you have a start() method but it's difficult to stop the thread because there is no working stop() method. Well, there was a stop() method in Thread class, when Java was first released but that was deprecated later. In today's Java version, You can stop a thread by using a boolean volatile variable.  If you remember, threads in Java start execution from the run() method and stop, when it comes out of the run() method, either normally or due to any exception. You can leverage this property to stop the thread. 

All you need to do is create a boolean variable like. bExit or bStop. Your thread should check its value every iteration and comes out of the loop and subsequently from the run() method if bExit is true. 

In order to stop the thread, you need to set the value of this boolean variable to true when you want to stop a running thread. Since you are setting this variable from a different thread e.g. main thread, it's important to mark this variable volatile, otherwise, it's possible for the running thread to cache its value and never check back to main memory for updated value and running infinitely.

When you make a variable volatile, the running thread will not cache its value in its local stack and always refer to the main memory. The volatile variable also provides happens before guarantee, which can be used to synchronize values. 

If you want to understand multi-threading and concurrency in the right way, I strongly suggest reading Java Concurrency in Practice twice. It's one of the most accurate, thorough, and practical books in Java multi-threading.




Stopping a Thread in Java - An Example

Here is our sample code example to stop a thread in Java. You can see that in this example, the main thread is first starting a thread, and later it's stopping that thread by calling our stop() method, which uses a boolean volatile variable to stop running thread e.g. Server.  

From the output, it's clear that our Server, which implements Runnable is running fine until the main() method called the stop() method, the only then value of boolean volatile variable exit is set to true

In the next iteration, our Server thread checks and find this value true, so it comes out of the loop and runs () method, which means your thread is now stopped. See these Java Concurrency courses to learn more about it. 

Using boolean volatile variable to stop a thread in Java


Here is the Java program to demonstrate how to stop a thread in Java using a boolean volatile variable, You can also see here for a similar approach.

import static java.lang.Thread.currentThread;

import java.util.concurrent.TimeUnit;

/**
 * Java Program to demonstrate how to stop a thread in Java.
 * There is a stop() method in Thread class but its deprecated 
 * because of deadlock and other issue, but its easy to write
 * your own stop() method to stop a thread in Java. 
 * 
 * @author java67
 */

public class ThreadStopDemo {

    public static void main(String args[]) throws InterruptedException {
        Server myServer = new Server();

        Thread t1 = new Thread(myServer, "T1");
        t1.start();
        
        //Now, let's stop our Server thread
        System.out.println(currentThread().getName() 
                           + " is stopping Server thread");
        myServer.stop();
        
        //Let's wait to see server thread stopped 
        TimeUnit.MILLISECONDS.sleep(200);
        
        System.out.println(currentThread().getName() + " is finished now");
    }
}

class Server implements Runnable{
    private volatile boolean exit = false;
    
    public void run() {
        while(!exit){
            System.out.println("Server is running.....");
        }
        
        System.out.println("Server is stopped....");
    }
    
    public void stop(){
        exit = true;
    }
}

Output
Server is running.....
Server is running.....
Server is running.....
Server is running.....
Server is running.....
Server is running.....
Server is running.....
Server is running.....
Server is running.....
Server is running.....
main is stopping Server thread
Server is running.....
Server is stopped....
main is finished now


Things to remember

1. Please ensure that the boolean variable which is used to stop the thread is volatile, otherwise, in the worst case, your thread may not stop and run infinitely, Why? because, in the absence of any synchronization instruction like volatile modifier here, the compiler is free to cache the value of boolean variable exit, which means even if the main thread makes it true, the Server will always see it false, thus running infinitely. This concept is often tested in Java interviews as well.

2. It's always better to check for a boolean variable in your while loop, it could be your game loop or main server loop used to process requests.

3. It's good to provide a method to stop the server, which does nothing but changes the value of a boolean variable.

4. Using TimeUnit class to pause a thread is better than the Thread.sleep() method because it improves readability. You know upfront that whether a thread is stopping for 2 milliseconds or 2 seconds, which was not visible in the case of Thread.sleep().  See here to learn more about TimeUnit class.


That's all about how to stop a thread in Java. Make sure to check for stopping conditions in a while loop and ensure that the boolean volatile variable. This will guarantee two things, first, the thread which is checking this boolean variable will not cache its value in its local cache and second any change made on one thread before setting this volatile boolean variable will be visible to other thread as well.

If you like this short tutorial and are interested to learn Java in deep, here are a couple of more interesting articles you will enjoy :
  • What is the difference between the transient and volatile variables in Java? [answer]
  • How to pause a thread in Java? [example]
  • What is the difference between a thread and a process? [answer]
  • What is the difference between implements Runnable and extends Thread in Java? [answer]
  • 10 things you should know about Thread in Java? [article]
  • When to use the wait() and sleep() method in Java? [answer]
  • Difference between a Callable and a Runnable interface in Java? [answer]
In the real world, though, you may need to give your thread some time to finish the pending tasks, release resources and do cleanup before stopping.

9 comments:

  1. You really should consider joining on the Server's thread, this is the only way to know for certain that the thread is finished.

    ReplyDelete
    Replies
    1. @Anonymous, you are correct, join() would have been better choice there, but I have opted sleep for simplicity.

      Delete
    2. How is join() less simple than sleep()? I'd say it's the other way around.

      Delete
  2. In the above example, If we use t1.join() after t1.start() , it will go in infinite loop, and the control would never return to main().

    ReplyDelete
  3. @Unknown yes control will never go to main method .
    https://docs.oracle.com/javase/tutorial/essential/concurrency/join.html
    The join method allows one thread to wait for the completion of another.
    as in the code while(!exit){...} the value for exit is false it is never changing to true(as myServer.stop() called in main method ),so it will go to a infinite loop.

    ReplyDelete
  4. how to control execution of threads?
    suppose that you have two thread, then execution of two thread is..
    thread1 1
    thread2 1
    thread1 2
    thread2 2
    thread1 3
    thread2 3
    and so on...

    ReplyDelete
    Replies
    1. after two thread start join() method call it will stop next processing when ever the two thread has to complete their work

      Delete
  5. Good article Javin.

    The volatile flag solution is nice and simple, and works in most cases, but it might not be the best option if the Thread you want to stop might potentially block in a call to Object.wait, sleep for long periods, wait for a lock to be released, wait for a queue to have some value available, etc.

    I wrote an article about this in my blog, feel free to check it out:
    https://thevalenciandev.com/2019/01/30/stopping-threads-correctly-in-java/

    Cheers

    ReplyDelete
  6. Hello I study in engineering. I learning Java in this blog

    ReplyDelete

Feel free to comment, ask questions if you have any doubt.