4

I have a program which creates 10 threads, and each thread has an infinitely running while loop. I need help to efficiently implement a Shutdown hook which can effectively STOP all the threads. Since I want to do a graceful shutdown each Thread should finish as soon as it finds the stop flag turned to TRUE.

public class SampleGSH implements Runnable{
    private static boolean stop = false;
    public static void main(String[] args) {
        for(int i = 0; i < 10;i++) {
            Thread t = new Thread(new SampleGSH(), "name"+i);
            t.start();
        }
    }

    @Override
    public void run() {
            Runtime.getRuntime().addShutdownHook(new Thread("shutdown thread") {
                public void run()
                {
                    System.out.println("*******");
                    synchronized (this) 
                    {
                        System.out.println("Turning switch off");
                        stop = true;
                    }
                }
            });

            synchronized (this) {
                while(!stop)
                {
                      //Some logic which should not be killed abruptly once it starts running, a graceful shut down will not allow this code to start
                }
            }   
    }
}

Any help will be truly appreciated.

rgettman
  • 176,041
  • 30
  • 275
  • 357
Suyog Barve
  • 237
  • 3
  • 10

3 Answers3

1

I need help to efficiently implement a Shutdown hook which can effectively STOP all the threads.

If you have any fields that are shared between multiple threads, they need to be synchronized. In this case your stop should be volatile. Without this, there is nothing that ensures that the threads will see the value of stop change to true. See this tutorial for information about atomic access.

See: Using boolean var for stopping threads

Couple other comments:

  • If you are starting a number of threads, you should consider using an ExecutorService

  • Your while loop is inside of a synchronized block. This does nothing and the stop field will not get memory synchronized since it gets updated externally while inside of the block.

  • Another way to stop a thread would be to interrupt() it. See this tutorial.

      while (!thread.currentThread().isInterrupted()) {
          ...
      }
      ...
      t.interrupt();
    
Gray
  • 115,027
  • 24
  • 293
  • 354
1

Instead of a single static stop boolean, you could give every thread its own stop boolean. Then store all thread objects when creating them and set their stop boolean to true in the shutdown hook thread (which would be hooked in the main method).

Something like this:

import java.util.ArrayList;
import java.util.List;

public class SampleGSH extends Thread {

    public boolean stop = false;
    private static List<SampleGSH> threads = null;

    public static void main(String[] args) {

        threads = new ArrayList<SampleGSH>();

        int numThreads = 10;
        for (int i = 0; i < numThreads; i++) {
            SampleGSH t = new SampleGSH();
            threads.add(t);
            t.start();
        }

        Runtime.getRuntime().addShutdownHook(new Thread("shutdown thread") {
            public void run() {
                System.out.println("*******");
                for (SampleGSH t : threads) {
                    t.stop = true;
                }
            }
        });
    }

    @Override
    public void run() {
        {
            while (!stop) {
                // Some logic which should not be killed abruptly once it starts
                // running, a graceful shut down will not allow this code to
                // start
            }
        }
    }
}
Barry NL
  • 963
  • 1
  • 9
  • 16
  • Or just use thread.interrupt() and thread.isInterrupted() methods instead as @Gray suggests. – Barry NL May 05 '13 at 19:00
  • thread.interrupt() will work only when thread's run method is catching InterruptedException (through Thread.sleep() method or any other method that throws InterruptedException). If the thread is not catching InterruptedException, interrupting it won't have any effect. In that case your solution is the better one, right? Even if run method is catching InterruptedException (say it has Thread.sleep() method), we need to hope that control is on Thread.sleep for interruption to take effect. If the control is somewhere else, interruption may still not work. – Sagar Jul 31 '20 at 05:26
1

Forget that addShutdownHook guff ... keep it simple ...

  1. Make the static stop variable volatile ...

  2. then add this method to SampleGSH ...

    public void shutdown() { stop = true; }

  3. then call it when you want to stop the threads!

xagyg
  • 9,562
  • 2
  • 32
  • 29