java - Java进程什么时候在shutdown hook后终止?

标签 java shutdown

我的问题是我的关闭发生得太早了,没有等待进程自行清理。

但是,如果在我的关闭线程中添加一个 while(true) Thread.sleep(1000);,该进程会很好地清理,并且显然永远不会关闭。

这让我感到困惑,因为关闭在许多非守护线程完成之前完成。例如,如果我编写一个非常简单的测试程序,其中 main() 无限循环并且关闭线程不会,则 main 无论如何都会终止(没有任何来自捕获 InterruptedException 的异常跟踪。

据我所知,关闭是在关闭线程 run 方法完成时发生的。我认为根据这些知识,我可以通过在轮询循环中结束它来解决这个问题,轮询表示成功关闭其余进程的 Future 。但这似乎是错误的 - 我真的只想等待所有非守护线程关闭,而且我当然不想进行轮询。

  1. 当关闭钩子(Hook)的线程的 run 方法完成时,关闭也会完成,我这样说对吗?
  2. 执行关闭、等待实际关闭任务完成的良好实践方法是什么?

最佳答案

通常,Java 进程可以在所有非守护线程终止后停止。这通常是虚拟机调用关闭 Hook 的时间。

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

,钩子(Hook)将被提前调用(即一些非守护线程仍然存在)

如果我理解正确,您会尝试在所有其他非守护线程完成后执行某些操作(即等待所有其他关闭线程完成)。

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

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

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

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

编辑java.lang.Shutdown中的代码是单线程的,因此如果其中一个关闭 Hook 阻塞,整个虚拟机就会挂起。

现在回答你的问题:

  1. 当调用 halt() 时,VM 将终止。这是 Terminate.run() 所做的最后一件事,所以是的,VM 应该run() 结束时真正终止。我什至不认为 run() 会返回。可能存在错误和 native 代码可能会造成妨碍,但这就是它应该的样子。

  2. 一个好的做法是使用线程池来完成您的工作并等待它们完成。关闭 Hook 是最后的手段。由于您无法真正影响顺序,并且无法确定非守护线程是否仍然存在,因此它们对于“最后关闭灯”类型的工作来说很脆弱。

    使用线程池,您可以拥有多个独立的线程池,您可以清楚地定义如何关闭线程池以及如何等待它们完成。最重要的是,您可以以可以中止线程的方式构建线程。当您处于关闭状态并且一个非守护线程拒绝终止时,您会做什么?使用线程池,您将知道内部可能存在的线程类型以及简单终止它的风险。

关于java - Java进程什么时候在shutdown hook后终止?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17574406/

相关文章:

java - 使用 Libgdx 与 box2d 寻找行为?

java - 对单表的日期、整数和字符串数据类型字段执行多列搜索?

python - 网络中断前的 Linux 关机/重启通知

linux - debian 服务器上的关机监视器

linux - 在 SysVinit 中关闭之前执行具有 curl 调用的脚本

java - 如何通过 JRuby 使用 Compass,嵌入到我的软件中?

java - Eclipse 是否有用于 JavaBeans 组件的 bean 构建器 UI?

c - Linux:以编程方式获取系统关机时间?

Android - 关机前发送短信

java - 我们可以传递方法参数的值和注释吗