4

I am new to Java/threads and I inherited something like the following code. It is a command line program that main() only starts 5-6 different kind of threads and exits with ^C. I want to add a shutdown hook to close all threads properly and adapted it the following way.

I added a Shutdown hook and a stopThread() method in all threads (like the one in MyWorker class)

The problem is that when I press ^C I don't see the end message from the Thread's run method. Is this done in the background or is there something wrong with my method. Also, Is there a better pattern I should follow?

Thanks

 public class Main {
     public static MyWorker worker1 = new MyWorker();
     // .. various other threads here

     public static void startThreads() {
         worker1.start();
         // .. start other threads
     }

     public static void stopThreads() {
         worker1.stopThread();
         // .. stop other threads
     }

     public static void main(String[] args)
             throws Exception {

         startThreads();

         // TODO this needs more work (later)

         Runtime.getRuntime().addShutdownHook(new Thread() {
             @Override
             public void run() {
                 try {
                     stopThreads();
                 } catch (Exception exp) {

                 }
             }
         });
     } }

 public class MyWorker extends Thread {
     private volatile boolean stop = false;

     public void stopThread() {
         stop = true;
     }

     public void run() {
         while (!stop) {
             // Do stuff here
         }
         // Print exit message with logger
     } 
}
2
  • 3
    You should declare stop volatile. Commented Sep 13, 2012 at 10:59
  • Good point (edited the question too) ;) but doesn't solve the problem. Commented Sep 13, 2012 at 18:49

5 Answers 5

11

Shutdown Hooks may not be executed in some cases!

First thing to keep in mind is that it is not guaranteed that shutdown hooks will always run. If the JVM crashes due to some internal error, then it might crash down without having a chance to execute a single instruction.

Also, if the O/S gives a SIGKILL (http://en.wikipedia.org/wiki/SIGKILL) signal (kill -9 in Unix/Linux) or TerminateProcess (Windows), then the application is required to terminate immediately without doing even waiting for any cleanup activities. In addition to the above, it is also possible to terminate the JVM without allowing the shutdown hooks to run by calling Runime.halt() method.

Shutdown hooks are called when the application terminates normally (when all threads finish, or when System.exit(0) is called). Also, when the JVM is shutting down due to external causes such as user requesting a termination (Ctrl+C), a SIGTERM being issued by O/S (normal kill command, without -9), or when the operating system is shutting down.

Sign up to request clarification or add additional context in comments.

Comments

8

When you call System.exit() or terminate via a signal, it stop all the existing threads and starts all the shutdown hooks. i.e. all your threads could be dead by the time you hook starts.

Instead of trying to stop threads cleanly, you should ensure resources are closed cleanly.

2 Comments

How can I handle the Tread termination from the tread itself? i.e. call some code for cleanup.
Point of clarification, per the java.lang.Runtime.addShutdownHook() javadoc: "Note that daemon threads will continue to run during the shutdown sequence, as will non-daemon threads if shutdown was initiated by invoking the exit method." So, calling System.exit() should behave differently than most other shutdowns that apparently behave the way Peter described.
5

I guess you can shift your code to ExecutorService

private final ExecutorService pool;
pool = Executors.newFixedThreadPool(poolSize);
pool.execute(Instance of Runnable);
pool.shutdown(); 

ExecutorService.shutdown

Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted. Invocation has no additional effect if already shut down.

5 Comments

I wonder if this will work in case of stopping program by hitting Ctrl-C on the command line ? How will pool.shutdown() be called ? I believe in the jvm shutdown hook...
Yes also awaitTermination can be used from shutdown hook but though it gaurantees that it will get executed most of the time it can never gaurantee that always.
In my case I guess this doesn't work. I have 5-6 different types of Threads: 3 kinds of producers, 1 consumer and a couple of other supplementary threads.
It may not be working for some other reason. It should work with different types of threads. Java threads implement the interface Runnable.
It may not be working for some other reason. It should work with different types of threads. Java threads implement the interface Runnable. Can you have any other mechanism to shut down, other than Ctrl C ? Some prompt for a command maybe ? Enter "exit" to stop program. And then you call pool.shutdown()
2

Try making your threads as daemon threads.

Add a constructor

public MyWorker(boolean isDaemon) {
this.setDaemon(true);
}

or set to daemon before calling start.

worker1.setDaemon(true);
worker1.start();

When you press Ctrl C and exit, the threads will be stopped.

Comments

0

What is happening here is that you invoke the stopThread() method, but you don't wait the the threads are actually finished before terminating.

If you invoke a join() on all threads before stoping the JVM, you will probably see your 'stop logs'.

public static void stopThreads() {
     worker1.stopThread();
     // .. stop other threads

    for(Thread t: workers) {
       t.join();
    }
 }

1 Comment

I already tried this but didn't work. I even tried to join them on the main() function after the startThread() / Shutdown hook

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.