关闭挂钩后Java进程何时死亡?

时间:2013-07-10 15:14:11

标签: java shutdown

我的问题是我的关机也在早期发生,而不是等待进程自我清理。

但是,如果在我的关机线程中我添加while(true) Thread.sleep(1000);,则该过程可以很好地清理,显然,永远不会关闭。

这让我很困惑,因为在许多非守护程序线程完成之前关闭完成。例如,如果我编写一个非常简单的测试程序,其中main()无限循环和关闭线程不会,main将被终止(没有任何异常跟踪来自catch {{1 }}为s)。

因此,当关闭线程InterruptedException方法完成时,我可以告诉关闭。我想从这个知识我可以通过在轮询循环中结束它来修复它,轮询一个run表示成功关闭其余进程。但这似乎是错误的 - 我真的只是想等待所有非守护程序线程关闭,我当然不想进行民意调查。

  1. 当关闭hook的线程的Future方法完成时,我是否正确关闭完成?
  2. 执行关机,等待实际关机任务完成的好方法是什么?

2 个答案:

答案 0 :(得分:2)

通常,Java进程可以在所有非守护程序线程终止后停止。这通常是VM调用关闭挂钩的时间。

如果您终止进程或调用System.exit()

,将会提前调用挂钩(即,某些非守护程序线程仍然存在)

如果我理解正确,你会在所有其他非守护程序线程完成后尝试做某事(即等待所有其他关闭线程完成)。

这不容易实现。您可以尝试访问根ThreadGroup(它没有父级,使用Thread.currentThread().getGroup()然后向上移动链接)。所有线程都是该组的子级(或其子组)。

因此,您可以迭代此树,直到只剩下守护程序线程:

int maxWait = 100;
while(countNonDaemonThreads() > 0 && --maxWait > 0) {
    Thread.sleep(100);
}

这应该可行,但我还没有测试过。请注意,您需要注意关闭线程中的代码;它必须不会阻塞,你必须以某种方式处理所有错误,否则VM可能无法正常终止。

编辑 java.lang.Shutdown中的代码中的代码是单线程的,因此如果其中一个关闭挂钩阻塞,则整个VM都会挂起。

现在回答你的问题:

  1. 当调用halt()时,VM终止。这是Terminate.run()做的最后一件事,所以是的,VM 应该真正终止于run()。我甚至认为run()永远不会回来。可能存在错误和本机代码可能会妨碍它,但这应该是它应该如何。

  2. 一个好的做法是使用线程池来完成工作并等待它们完成。关机挂钩是最后的选择。既然你不能真正影响秩序,你就无法确定非守护程序线程是否仍然存在,它们对于“最后一次关灯”的工作是脆弱的。

    使用线程池,您可以拥有多个独立的线程池,您可以干净地定义如何关闭池以及如何等待它们完成。最重要的是,您可以以可以中止它们的方式构建线程。当你处于关闭钩子并且一个非守护进程线程拒绝死亡时,你打算做什么?使用线程池,您将知道可能在其中的线程类型以及简单地终止它的风险。

答案 1 :(得分:1)

  

当关闭hook的线程运行方法完成时,我是否正确关闭完成?   执行关闭,等待实际关闭任务完成的好方法是什么?

使你的关闭线程非守护进程

如果这还不够,您的代码中就会出现错误。你可以向自己证明一个没有退出的关闭钩子不会被提前杀死。