我的问题是我的关机也在早期发生,而不是等待进程自我清理。
但是,如果在我的关机线程中我添加while(true) Thread.sleep(1000);
,则该过程可以很好地清理,显然,永远不会关闭。
这让我很困惑,因为在许多非守护程序线程完成之前关闭完成。例如,如果我编写一个非常简单的测试程序,其中main()
无限循环和关闭线程不会,main
将被终止(没有任何异常跟踪来自catch {{1 }}为s)。
因此,当关闭线程InterruptedException
方法完成时,我可以告诉关闭。我想从这个知识我可以通过在轮询循环中结束它来修复它,轮询一个run
表示成功关闭其余进程。但这似乎是错误的 - 我真的只是想等待所有非守护程序线程关闭,我当然不想进行民意调查。
Future
方法完成时,我是否正确关闭完成?答案 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都会挂起。
现在回答你的问题:
当调用halt()
时,VM终止。这是Terminate.run()
做的最后一件事,所以是的,VM 应该真正终止于run()
。我甚至认为run()
永远不会回来。可能存在错误和本机代码可能会妨碍它,但这应该是它应该如何。
一个好的做法是使用线程池来完成工作并等待它们完成。关机挂钩是最后的选择。既然你不能真正影响秩序,你就无法确定非守护程序线程是否仍然存在,它们对于“最后一次关灯”的工作是脆弱的。
使用线程池,您可以拥有多个独立的线程池,您可以干净地定义如何关闭池以及如何等待它们完成。最重要的是,您可以以可以中止它们的方式构建线程。当你处于关闭钩子并且一个非守护进程线程拒绝死亡时,你打算做什么?使用线程池,您将知道可能在其中的线程类型以及简单地终止它的风险。
答案 1 :(得分:1)
当关闭hook的线程运行方法完成时,我是否正确关闭完成? 执行关闭,等待实际关闭任务完成的好方法是什么?
使你的关闭线程非守护进程
如果这还不够,您的代码中就会出现错误。你可以向自己证明一个没有退出的关闭钩子不会被提前杀死。