这样,信号将被转发给它们,从而允许在标准方式.
但事实并非如此(至少在我的JVM实现中:Java(TM) SE Runtime Environment (build 1.8.0_25-b17), Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode).
正如其他用户所评论的,停机钩似乎是强制性的。
那我该怎么处理呢?
首先,我不关心所有的程序,只有在那些我想要跟踪的用户取消和意外的目的。例如,假设您的java程序是由其他人管理的进程。您可能需要区分它是否已优雅地终止(SIGTERM或者发生了关闭(以便在启动时自动重新启动作业)。
作为一个基础,我总是定期地使我的长时间运行的线程注意到中断的状态,并抛出InterruptedException如果他们打断了。这允许由开发人员控制的执行终结(也产生与标准阻塞操作相同的结果)。然后,在线程堆栈的顶层,InterruptedException被捕获并执行适当的清理。这些线程被编码为知道如何响应中断请求。高衔接设计。
因此,在这些情况下,我添加了一个关机钩子,这做了我认为JVM默认应该做的事情:中断我的应用程序创建的、仍在运行的所有非守护进程线程:Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
System.out.println("Interrupting threads");
Set runningThreads = Thread.getAllStackTraces().keySet();
for (Thread th : runningThreads) {
if (th != Thread.currentThread()
&& !th.isDaemon()
&& th.getClass().getName().startsWith("org.brutusin")) {
System.out.println("Interrupting '" + th.getClass() + "' termination");
th.interrupt();
}
}
for (Thread th : runningThreads) {
try {
if (th != Thread.currentThread()
&& !th.isDaemon()
&& th.isInterrupted()) {
System.out.println("Waiting '" + th.getName() + "' termination");
th.join();
}
} catch (InterruptedException ex) {
System.out.println("Shutdown interrupted");
}
}
System.out.println("Shutdown finished");
}});