ScheduledExecutorService 和 Shutdown 挂钩
ScheduledExecutorService and Shutdown Hook
当我使用 ScheduledExecutorService
(或 ExecutorService)并提交 Runnable 时,我的关闭挂钩从未被调用。例如,此程序挂起:
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);
}
}
由于执行者的线程不是守护进程,我希望调用关闭挂钩,但事实并非如此。知道为什么吗?
来自 Runtime#addShutdownHook(Thread)
的 javadoc:
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.*
正如您自己所说,newSingleThreadScheduledExecutor
返回的 Executor
中的线程不是守护线程。所以他们必须在你的关闭钩子被调用之前退出。
你在倒退。您需要从程序执行的其他部分关闭 Executor
,而不是关闭挂钩。 Executor
终止后,关闭挂钩将 运行。
* 假设您没有尝试向 java
进程发送用户中断。
如果您绝对需要在任务完成后关闭执行程序 运行,您可以执行如下操作:
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);
}
当我使用 ScheduledExecutorService
(或 ExecutorService)并提交 Runnable 时,我的关闭挂钩从未被调用。例如,此程序挂起:
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);
}
}
由于执行者的线程不是守护进程,我希望调用关闭挂钩,但事实并非如此。知道为什么吗?
来自 Runtime#addShutdownHook(Thread)
的 javadoc:
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.*
正如您自己所说,newSingleThreadScheduledExecutor
返回的 Executor
中的线程不是守护线程。所以他们必须在你的关闭钩子被调用之前退出。
你在倒退。您需要从程序执行的其他部分关闭 Executor
,而不是关闭挂钩。 Executor
终止后,关闭挂钩将 运行。
* 假设您没有尝试向 java
进程发送用户中断。
如果您绝对需要在任务完成后关闭执行程序 运行,您可以执行如下操作:
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);
}