Reputation: 4448
When I use a ScheduledExecutorService
(or ExecutorService) and submit a Runnable, my shutdown hook never gets called. Ex, this program hangs:
public class App {
static ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
static {
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
exec.shutdownNow();
}
});
}
public static void main(String[] args) {
exec.schedule(new Runnable() {
@Override
public void run() {
}
}, 10, TimeUnit.SECONDS);
}
}
Since the executor's thread is not a daemon, I would expect the shutdown hook to be called, but it's not. Any idea why?
Upvotes: 1
Views: 4052
Reputation: 558
In the event you absolutely need to shutdown the executor after the task has run you can implement something like this:
static {
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
Logger.getGlobal().info("destroying");
exec.shutdownNow();
}
});
}
public static void main(String[] args) throws Exception {
Future f = exec.schedule(new Runnable() {
@Override
public void run() {
Logger.getGlobal().info("thread run");
}
}, 10, TimeUnit.SECONDS);
while (!f.isDone()) {
Logger.getGlobal().info("waiting for task to finish");
Thread.sleep(1000);
}
Runtime.getRuntime().exit(0);
}
Upvotes: 0
Reputation: 280174
From the javadoc of Runtime#addShutdownHook(Thread)
:
The Java virtual machine shuts down in response to two kinds of events:
- The program exits normally, when the last non-daemon thread exits or when the exit (equivalently, System.exit) method is invoked, or
- The virtual machine is terminated in response to a user interrupt, such as typing ^C, or a system-wide event, such as user logoff or system shutdown.*
As you said yourself, the threads in the Executor
returned by newSingleThreadScheduledExecutor
are not daemon threads. So they must exit before your shutdown hook can be invoked.
You're doing things backwards. You need to shutdown your Executor
from some other part of your program's execution, not the shutdown hook. The shutdown hook will run after the Executor
has terminated.
* Assuming you aren't trying to send a user interrupt to your java
process.
Upvotes: 3