I want to achieve the following: When my application starts, the main thread will start 1+ worker threads that should run in the background, and periodically do things behind the scenes. These should not block the main thread: once main starts the workers, it continues doing its own thing until:
The main thread finishes (normal application termination) - in the case of a command-line utility this is when the end of the main(String[]) method is reached; in the case of a Swing GUI it could be when the user selects the File >> Exit menu, etc.
The operating system throws a kill command (SIGKILL, etc.)
An unexpected, uncaught exception occurs in the main thread, effectively killing it (this is just an unpolite version of #1 above)
Once started/submitted from the main thread, I want all the worker threads (Runnables) to essentially have their own life cycle, and exist independently of the main thread. But, if the main thread dies at any time, I want to be able to block (if at all possible) the main thread until all the workers are finished shutting down, and then "allow" the main thread to die.
My best attempt so far, although I know I'm missing pieces here and there:
public class MainDriver {
private BaneWorker baneWorker;
private ExecutorService executor = Executors.newCachedThreadPool();
public static void main(String[] args) {
MainDriver driver = new MainDriver();
driver.run();
// We've now reached the end of the main method. All workers should block while they shutdown
// gracefully (if at all possible).
if(executor.awaitTermination(30, TimeUnit.SECONDS))
System.out.println("Shutting down...");
else {
System.out.println("Forcing shut down...");
executor.shutdownNow();
}
}
private void run() {
// Start all worker threads.
baneWorker = new BaneWorker(Thread.currentThread());
// More workers will be used once I get this simple example up and running...
executor.submit(baneWorker);
// Eventually submit the other workers here as well...
// Now start processing. If command-line utility, start doing whatever the utility
// needs to do. If Swing GUI, fire up a parent JFrame and draw the application to the
// screen for the user, etc.
doStuff();
}
private void doStuff() {
// ??? whatever
}
}
public class BaneWorker implements Runnable {
private Timer timer;
private TimerTask baneTask;
private Thread mainThread;
public BaneWorker(Thread mainThread) {
super();
this.mainThread = mainThread;
}
#Override
public void run() {
try {
timer = new Timer();
baneTask = new TimerTask() {
#Override
public void run() {
System.out.println("When the main thread is ashes...");
}
};
// Schedule the baneTask to kick off every minute starting now.
timer.scheduleAtFixedRate(baneTask, new Date(), 60 * 1000);
} catch(InterruptedException interrupt) {
// Should be thrown if main thread dies, terminates, throws an exception, etc.
// Should block main thread from finally terminating until we're done shutting down.
shutdown();
}
}
private void shutdown() {
baneTask.cancel();
System.out.println("...then you have my permission to die.");
try {
mainThread.join();
} catch(InterruptedException interrupt) {
interrupt.printStackTrace;
}
}
}
Am I on-track or way off-base here? What do I need to change to make this work the way I need it to? I'm new to Java concurrency and am trying my best to use the Concurrency API correctly, but stumbling around a bit. Any ideas? Thanks in advance!
The main thread must signal the worker threads to terminate (generally this is achieved just by using a flag) and then it should call join on every thread to wait for their termination. Have a look here: Java: How to use Thread.join
You can use Runtime.addShutdownHook to register an un-started thread that is executed when a JVM is terminated, the system is shutting down etc. This code can do some cleanup itself, or perhaps notify running daemon threads to finish their work. Any such cleanup code must be relatively fast, because on many systems programs have only a limited time to do cleanup before they're forcibly terminated.
Perhaps you could also consider making your background thread daemon threads. Then they will not block the JVM when main finishes and will be still running during the clean-up phase.
Note that you can't intercept SIGKILL - this signal is designed to be unavoidable and immediate. But it should work with SIGTERM, SIGHUP and similar signals.
Update: You can easily create ExecutorServices that run daemon threads. All you need is to create a proper ThreadFactory:
public static class DaemonFactory
implements ThreadFactory
{
#Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
}
than you create an ExecutorService like
public static void main(String argv[])
throws Exception
{
ExecutorService es
= Executors.newCachedThreadPool(new DaemonFactory());
// ^^^^^^^^^^^^^^^^^^^
es.submit(new Callable<Object>() {
public Object call() throws Exception {
Thread.sleep(100);
System.err.println("Daemon: " +
Thread.currentThread().isDaemon());
return null;
}
});
// Without this, JVM will terminate before the daemon thread prints the
// message, because JVM doesn't wait for daemon threads when
// terminating:
es.awaitTermination(3, TimeUnit.SECONDS);
}
Concerning Thread.join(), you shouldn't try to use it on threads managed by an ExecutorService. It's the responsibility of the executor to manage them. You have no reliable way how to enumerate its threads, the executor can create and destroy threads depending on its configuration etc. The only reliable way is to call shutdown(); and then awaitTermination(...);.
If SIGKILL is a unix "kill -9" there's nothing you can do about it.
For graceful exits, use a try/catch/finally in your main. The catch will catch your exceptions and allow you to do what needs to be done (recover? abort?) The finally will give you the hook to spin down your threads gracefully.
Reviewing your code quickly, I don't see where you're keeping track of your thread instances. You'll need those if you're going to tell them to spin down.
psuedocode:
static Main(...) {
ArrayList threads = new ArrayList();
try {
for (each thread you want to spin up) {
threads.add(a new Thread())
}
}
catch { assuming all are fatal. }
finally {
for(each thread t in threads) {
t.shutdown();
t.join(); /* Be prepared to catch (and probably ignore) an exception on this, if shutdown() happens too fast! */
}
}
Related
I am running simple thread which has run method as follows
public run()
while(!stopFlag){
// print something Line 1
// print something Line 2
// print something Line 3
// print something Line 4
}
If I run this thread through ExecutorService viz
ExecutorService exs = Executors.newFixedThreadPool(5);
exs.execute(new MyThread));
I stop the ExecutorService
exs.shutdown();
But this does not stop the thread as flag is not set to false. In another question related to same topic I was asked to properly handle InterruptedException which is caused when exs.shutdown() is called.
But in this case I am not doing any action that can throw InterruptedException.
What is the standard way to handle such case ?
Further question
Answer given by Sabir says "If your runnable doesn't respond well to interrupts, nothing can be done to stop it other than shutting down the JVM. ".This seems to be my case.
But how to introduce handling of InterruptedException; if I am not calling any method that throws interrupted exception?
If you are willing to shut your thread even if that flag remains true, you should use - ExecutorService.shutdownNow() method instead of ExecutorService.shutdown()
Quoting from Java Docs,
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.
This method does not wait for previously submitted tasks to complete
execution. Use awaitTermination to do that.
shutdownNow()
Attempts to stop all actively executing tasks, halts the processing of
waiting tasks, and returns a list of the tasks that were awaiting
execution.
This method does not wait for actively executing tasks to terminate.
Use awaitTermination to do that.
There are no guarantees beyond best-effort attempts to stop processing
actively executing tasks. For example, typical implementations will
cancel via Thread.interrupt, so any task that fails to respond to
interrupts may never terminate.
For standard way, I will quote from JDK example from ExecutorService interface,
Usage Examples
Here is a sketch of a network service in which threads in a thread pool service incoming requests. It uses the preconfigured Executors.newFixedThreadPool factory method: class NetworkService implements Runnable { private final ServerSocket serverSocket; private final ExecutorService pool;
public NetworkService(int port, int poolSize)
throws IOException {
serverSocket = new ServerSocket(port);
pool = Executors.newFixedThreadPool(poolSize); }
public void run() { // run the service
try {
for (;;) {
pool.execute(new Handler(serverSocket.accept()));
}
} catch (IOException ex) {
pool.shutdown();
} } }
class Handler implements Runnable { private final Socket socket; Handler(Socket socket) { this.socket = socket; } public void run() {
// read and service request on socket } }} The following method shuts down an ExecutorService in two phases, first by calling shutdown to reject incoming tasks, and then calling shutdownNow, if necessary, to cancel any lingering tasks: void shutdownAndAwaitTermination(ExecutorService pool) { pool.shutdown(); // Disable new tasks from being submitted try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
} } catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt(); } }}
Notice that there are no guarantees even with shutdownNow() .
EDIT : If I change your while(!stopFlag) to while(!Thread.currentThread().isInterrupted()) then thread with conditional loop get shutdown with shutdownNow() but not with shutdown() so thread gets interrupted with shutdownNow(). I am on JDK8 and Windows 8.1. I do have to put a sleep in main thread so that service can get time to set up the service and launch runnable. Thread gets launched, goes in while then stops when shutdownNow() is called. I don't get that behavior with shutdown() i.e. thread never comes out of while loop. So the approach to make your runnables responsible for interrupts should be there ,either by checking flags or handling exceptions. If your runnable doesn't respond well to interrupts, nothing can be done to stop it other than shutting down the JVM.
One good approach is shown here
well from your question I am assuming that you are trying to shutdown the process gracefully. In order to do so you need to register a shutdownHook to achieve it. Here is a sample code to achieve it.
package com.example;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadManager {
public static void main(String[] args) {
MyThread myThread = new MyThread();
Runtime.getRuntime().addShutdownHook(new Thread(){
MyThread myThread = null;
#Override
public void run(){
System.out.println("Shutting down....");
this.myThread.stopProcess();
}
public Thread setMyThread(MyThread myThread){
this.myThread=myThread;
return this;
}
}.setMyThread(myThread));
ExecutorService exs = Executors.newFixedThreadPool(5);
myThread.setName("User");
exs.execute(myThread);
exs.shutdownNow();
}
}
And in MyThread.java will be look like following:-
package com.example;
public class MyThread extends Thread{
private boolean stopFlag;
#Override
public void run(){
while(!stopFlag){
System.out.println(this.getName());
}
}
public void stopProcess(){
this.stopFlag=true;
}
}
Now if you make a jar file of this code and run the in a Linux server to see how it is working, then follow these additional steps
Step 1> nohup java -jar MyThread.jar &
Press ctrl+c to exist
Now find the pid using following command
Step 2> ps -ef| grep MyThread.jar
Once you got the pid than execute the following command to stop gracefully
Step 3>kill -TERM <Your PID>
When you check the nohub.out file, the output will looks something like following
User
User
.
.
.
User
Shutting down....
User
.
.
Remember if you try to shutdown using kill -9 than you will never see the Shutting down.... message.
#Sabir already discuss the difference between shutdown and shutdownNow. However I will never recommend you to use interrupt call while the threads are running. It might cause memory leak in real time environment.
Upadte 1:-
public static void main(String[] args) {
MyThread myThreads[] = new MyThread[5];
ExecutorService exs = Executors.newFixedThreadPool(5);
for(int i=0;i<5;++i){
MyThread myThread = new MyThread();
myThread.setName("User "+i);
exs.execute(myThread);
myThreads[i] = myThread;
}
Runtime.getRuntime().addShutdownHook(new Thread(){
MyThread myThreads[] = null;
#Override
public void run(){
System.out.println("Shutting down....");
for(MyThread myThread:myThreads){
myThread.stopProcess();
}
}
public Thread setMyThread(MyThread[] myThreads){
this.myThreads=myThreads;
return this;
}
}.setMyThread(myThreads));
exs.shutdownNow();
}
I have a main thread that creates several threads using Executors
ExecutorService executor = Executors.newFixedThreadPool(4);
Each thread has long running jobs (some legacy code from another team) which might run for hours.
Now I want to shutdown from the main thread using
executor.shutdownNow()
And I want the threads to be able to stop immediately, how could I do that?
In the thread, say we have such code:
public void run() {
doA();
doB();
doC();
...
...
}
Now my issue is, even if I called shutdownNow, the running thread will run to the end then stop. I'd like to know how to stop and exit.
It's a slightly tricky situation indeed!
Can we make use of a hook that the JDK has provided in the form of ThreadFactory that is consulted when the associated thread pool is creating a thread in which your legacy task will run? If yes, then why not make your legacy code run in a daemon thread? We know that the JVM exits when the last non-daemon thread exits. So, if we make each thread that the thread pool uses to run your legacy tasks a daemon thread, there is a chance that we can make the shutdownNow() call more responsive:
public class LegacyCodeExecutorEx {
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(2, new DaemonThreadFactory());
executor.submit(new LegacySimulator());
Thread.sleep(1000);
executor.shutdownNow();
}
static class LegacySimulator implements Runnable {
private final AtomicLong theLong;
LegacySimulator() {
theLong = new AtomicLong(1);
}
#Override
public void run() {
for (long i = 10; i < Long.MAX_VALUE; i++) {
theLong.set(i*i);
}
System.out.println("Done!");
}
}
static class DaemonThreadFactory implements ThreadFactory {
#Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("Daemon Thread");
t.setDaemon(true);
return t;
}
}
}
If you play with setDaemon(true) line, you will see that this code either responds to the exit of the main thread (which is non-daemon) either immediately or takes its own sweet time to finish the task.
Is making your legacy-code-running threads daemon threads a possibility? If yes, you could give this a try.
You need to include a flag in the Runnable object instantiation that checks between tasks whether you need to stop or not.
public void run() {
if(timeToShutdown) return;
doA();
if(timeToShutdown) return;
doB();
/*etc*/
}
Threads in Java operate at a (relatively) low level. Short of directly shutting down the entire JVM, the only way to manually force the stop of a Thread is using Deprecated behavior from Java 1.0/1.1, which pretty much noone wants you to use.
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
}
}
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.
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.
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.
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.
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();
}
}
This is the second post I have on trying to end/quit threads using interrupts and dealing with Ctrl-c ends. I'm not sure I understand it but here is my best attempt. I need more clarity on the concepts, and please give code examples where you can.
There are two classes, the main class Quitit and another class thething. The main class.
When loading the program via the terminal (the case on Linux):
Java -jar Quitit.jar
When you Ctrl-c to close it am i correct in saying that you need to:
Runtime.getRuntime().addShutdownHook()
Your threads so that they are killed on shut down.
Is this to correct way to deal with that ?
Why does it not allow you to call a method so that it may close down gracefully?
When not shutting down via Ctrl-C and you wish to do so via Thread.Interrupt() then does the program below use it correctly ?
Am I correct in saying that Thread.Join() halts the calling thread until the targeted thread is dead before continuing?
How would you implement/call the same Runtime.getRuntime().addShutdownHook() on implements Runnable threads, instead of extends Thread ?
Quitit class:
public class Quitit extends Thread {
public Quitit(String name) {
try {
connect("sdfsd");
} catch (Exception ex) {
}
}
void connect(String portName) throws Exception {
Thread thh = new thething("blaghname");
Runtime.getRuntime().addShutdownHook(thh);
thh.start();
System.out.println("Thread Thh (thething) Started()");
while (true) {
try {
Thread.sleep(2000);
if (thh.isAlive()) {
System.out.println("Thread Thh (thething) isAlive");
if (thh.isInterrupted()) {
System.out.println("Thread Thh (thething) is Inturrupted Should be Shutting Down");
} else {
System.out.println("Thread Thh (thething) is Not Inturrupted");
thh.interrupt();
System.out.println("Thread Thh (thething) Inturrput Sent");
System.out.println("Thread Thh (thething) Joined()");
thh.join();
}
} else {
System.out.println("Thread Thh (thething) isDead");
System.out.println("Main Thread:: can now end After Sleep off 2 seconds");
Thread.sleep(2000);
System.out.println("MMain Thread:: Sleep Ended Calling Break");
break;
}
} catch (InterruptedException xa) {
System.out.println("Main Thread:: ending due to InterruptException second Break called");
break;
}
}
System.out.println("Main Thread:: Outside While(true) via Break call");
}
public static void main(String[] args) {
try {
Thread oop = new Quitit("");
Runtime.getRuntime().addShutdownHook(oop);
oop.start();
} catch (Exception ezx) {
System.out.println("Main Thread:: Not Expected Exception");
}
}
}
TheThing class:
public class thething extends Thread {
thething(String name) {
super(name);
}
#Override
public void run() {
while (true) {
try {
System.out.println("thething class:: Inside while(true) Loop, now sleeping for 2 seconds");
Thread.sleep(2000);
} catch (InterruptedException e) {
try {
System.out.println("thething class:: has been Inturrupted now sleeping for 2 seconds!!");
Thread.sleep(2000);
break; // Will Quit the While(true) Loop
} catch (InterruptedException ex) {
System.out.println("thething class:: Second InterruptedException called !!");
}
}
}
System.out.println("thething class:: Outside while(true) and now thread is dying");
}
}
OutPut::
run:
Thread Thh (thething) Started()
thething class:: Inside while(true) Loop, now sleeping for 2 seconds
Thread Thh (thething) isAlive
Thread Thh (thething) is Not Inturrupted
Thread Thh (thething) Inturrput Sent
Thread Thh (thething) Joined()
thething class:: has been Inturrupted now sleeping for 2 seconds!!
thething class:: Outside while(true) and now thread is dying
Thread Thh (thething) isDead
Main Thread:: can now end After Sleep off 2 seconds
MMain Thread:: Sleep Ended Calling Break
Main Thread:: Outside While(true) via Break call
FINISHED - BUILD SUCCESSFUL (total time: 8 seconds)
I am surprised to here that control-c is not killing your program. It does on my test programs and should under most Unix variants.
When you Ctrl-c to close it am i correct in saying that you need to (setup a shutdown hook) so the threads are killed on shut down.
No, this is not correct. Shutdown hooks are used when you want to explicitly cleanup up some processing. They have nothing to do with the running threads and how they terminate.
Why does it not allow you to call a method so that it may close down gracefully?
Because that's not it's job.
Is this to correct way to deal with that ?
I'm not sure what the "that" is. As others have mentioned, the JVM finishes when the last non-daemon thread finishes. At that point the JVM kills all daemon threads and exits. If you want a background thread to be killed on shutdown then you'd do something like:
Thething theThing = new TheThing();
// set it to be a daemon thread before it starts
theThing.setDaemon(true);
theThing.start();
If you are asking about the proper way to terminate a thread cleanly then you can either use a volatile boolean or interrupt the thread. Typically this means that the class that starts the thread, keeps a handle around do it. Since QuitIt started TheThing class it would do something like the following if it was using a volatile boolean:
void connect(String portName) throws Exception {
Thread thh = new TheThing("blaghname");
thh.start();
...
// we are ready to kill the thread now
tth.shutdown = true;
}
Then in TheThing, the run() method would do something like the following:
public class TheThing extends Thread {
volatile boolean shutdown = false;
public void run() {
while (!shutdown) {
...
// you can also test for shutdown while processing
if (shutdown) {
return;
}
}
}
}
When not shutting down via Ctrl-C and you wish to do so via Thread.interrupt() then does the program below use it correctly ?
Using Thread.interrupt() is another way you can signal your thread that you want it to shutdown. You can also use the thread interrupt flag in a similar manner to the boolean above:
void connect(String portName) throws Exception {
Thread thh = new TheThing("blaghname");
thh.start();
...
// we are ready to interrupt the thread now
tth.interrupt();
}
It is very important to realize that interrupting a thread sets a flag on the Thread. They thread still needs to handle the interrupt appropriately with code. Then in TheThing, the run() method would do something like the following:
public class TheThing extends Thread {
public void run() {
while (!Thread.currentThread().interrupted()) {
...
}
}
}
Interrupting also causes wait(), notify(), and other methods to throw InterruptedException. The proper way to deal with this is:
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// catching the interrupted exception clears the interrupt flag,
// so we need to re-enable it
Thread.currentThread().interrupt();
// probably you want to stop the thread if it is interrupted
return;
}
Am I correct in saying that Thread.join() halts the calling thread until the targeted thread is dead before continuing?
Yes. Calling join() (with no arguments) will pause the calling thread until the thread it is joining on finishes. So typically you set your shutdown flag or you interrupt the thread and then join with it:
tth.shutdown = true;
// or tth.interrupt()
tth.join();
How would you implement/call the same Runtime.getRuntime().addShutdownHook() on implements Runnable threads, instead of extends Thread ?
This question doesn't make any sense. If you are asking about how to shutdown a thread if you have implemented Runnable, then the same mechanisms that I mention above would work.
Another thing that factors into the discussion of control-c is signal handlers. They allow you to catch control-c (and other signals) so you can do something intelligent with them. They are very OS dependent (of course) and if you catch the interrupt signal (SIGINT is usually sent by control-c) and don't stop the JVM, you are going to have problems.
But in any case, you can do something like the following:
...
MyHandler handler = new MyHandler();
// catch the control-c signal, "TERM" is another common kill signal
Signal.handle(new Signal("INT"), handler);
...
private static class MyHandler implements SignalHandler {
#Override
public void handle(Signal arg0) {
// interrupt your threads
// clean up stuff
// set shutdown flags
// ...
}
}
Again, I would say that it is a bad practice to catch interrupt signal (control-c) and not take the JVM down.
You have many questions in your question. If you want to gracefully shutdown threads when Ctrl-C is hit, then register a shutdown hook, and in the code of this shutdown hook, gracefully shutdown your threads.
A Thread instance can be constructed by extending Thread, or by passing a Runnable to the Thread constructor. So, if you want the code of your shutdown hook to be implemented in a Runnable, just do the following:
Runnable r = new Runnable() {
#Override
public void run() {
try {
// code of the shutdown hook: ask running threads to exit gracefully
for (Thread t : threadsToShutDown) {
t.interrupt();
}
for (Thread t : threadsToShutDown) {
t.join();
}
}
catch (InterruptedException e) {
// too bad
}
}
};
Runtime.getRuntime().addShutdownHook(new Thread(r));
Note that the above will prevent the JVM to exit if one of the threads doesn't respond to the interrupt. Introducing a timeout would be a good idea.
Also note that you must NOT start the thread that you register as shutdown hook.
When you Ctrl-c to close it am i correct in saying that you need to: Runtime.getRuntime().addShutdownHook() your threads so that they are killed on shut down.
No.
As per the docs, addShutdownHook simply registers a thread that will be run when the VM is shut(-ting) down. In theory this would be used as an application-wide finalizer; something that would run when your process is ending, to "tidy up". However there are some issues with them, similar to the reasons why finalizers are not recommended, in fact. They aren't guaranteed to run if the process is terminated abruptly, so they can't do anything critical. They run at a delicate part in the lifecycle, so they may not be able to access or interact with objects in a way that you'd expect. And they need to run quickly, else risk the process being killed before they finish.
But anyway this is completely different to what you're thinking of. When the VM shuts down, your threads will exit, without you needing to.
And besides, you have to provide an unstarted thread as a shutdown hook, so I'm slightly surprised that you don't get an IllegalThreadState exception thrown on shutdown.
When not shutting down via Ctrl-C and you wish to do so via Thread.Interrupt()
That's not the "usual" way to exit a multithreaded program either.
You have (broadly) two options:
Start your threads as "daemons", then just leave them be. The program exits when no non-daemon threads are running, so when your main thread terminates, your program will exit even though your "worker" threads are still alive. This works best of course when your
Signal to your threads that they should exit, e.g. call a stop() method that sets a boolean flag, and have those threads allow themselves to terminate. A thread stops when its run() method returns. Generally threads only keep running while they're in some sort of loop. Simply letting your thread exit the ongoing loop when its told to exit will shut it down gracefully, as typically it will finish its current "chunk of work" before checking the flag.
Interrupting a thread doesn't do what you might expect. It just sets another boolean flag internally. Many blocking operations (such as filesystem/network/database methods) will periodically check this flag and throw an InterruptedException if it is set. This allows a blocking method to exit early, but is not guaranteed if the method isn't "well-behaved".
So in your example it works because Thread.sleep() does respond to interrupts, and you then consider this a signal to exit. If however you write your own method to calculate the millionth Fibonacci number, for example, interrupting the thread would do nothing unless your implementation explicitly checks Thread.currentThread().interrupted() between each iteration.
Also, interrupts can come from almost anywhere, and it's hard to ascribe a particular "meaning" to them. Are they a signal to kill the thread? A signal to give up on the current method because the client's bored? A signal to start from the top because new data has arrived? In non-trivial programs it's not entirely clear.
A much better approach, given this, is to use boolean flags to communicate the reason, and then interrupt after setting the flag. A thread that gets interrupted should then check its state to see what just happened, and work out what to do. For example, you could code thething.run() as
private boolean keepRunning = true;
public void run() {
while(keepRunning) {
try {
System.out.println("thething class:: Inside while(true) Loop, now sleeping for 2 seconds");
Thread.sleep(2000);
} catch (InterruptedException e) {
try {
System.out.println("thething class:: has been Inturrupted now sleeping for 2 seconds!!");
Thread.sleep(2000);
} catch (InterruptedException ex)
{
System.out.println("thething class:: Second InterruptedException called !!");
}
}
}
}
And in QuitIt, set thh.keepRunning = false before interrupting it (or even better, define a method such as thh.allWorkDone() which sets the flag, and call that).
Note that there is no way to forcibly stop another thread - with good reason - you need to signal for the thread to stop, and ensure that whatever's running in the thread observes and respects that signal.
Best by huge margin - use daemon threads with no explicit termination. Next, redesign app so I can use daemon threads with no explicit termination. Absolute last resort, when no other approach is remotely possible, any kind of explicit shutdown code such has been posted here.
When my application is ready to exit, either by closing a window or invoking the System.exit() method. Do I have to manually stop the threads I may have created or will Java take care of that for me?
In cases you use System.exit(). All the threads will stop whether or not they are daemon.
Otherwise, the JVM will automatically stop all threads that are daemon threads set by Thread.setDaemon(true). In other words, the jvm will only exit when only threads remaining are all daemon threads or no threads at all.
Consider the example below, it will continue to run even after the main method returns.
but if you set it to daemon, it will terminate when the main method (the main thread) terminates.
public class Test {
public static void main(String[] arg) throws Throwable {
Thread t = new Thread() {
public void run() {
while(true) {
try {
Thread.sleep(300);
System.out.println("Woken up after 300ms");
}catch(Exception e) {}
}
}
};
// t.setDaemon(true); // will make this thread daemon
t.start();
System.exit(0); // this will stop all threads whether are not they are daemon
System.out.println("main method returning...");
}
}
If you want stop threads before exit gracefully, Shutdown Hooks may be a choice.
looks like:
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
//Stop threads }
});
See: hook-design