执行端点调用时关闭线程消失

Shutdown thread disappears when performing endpoints call

我在 Ubuntu 16.04 LTS 上有一个 Java 应用 运行ning。

当应用程序收到关机信号时,关机顺序是运行,如下所示:

    Runtime.getRuntime().addShutdownHook(new Thread() {
        @Override
        public void run() {
            shutdown();
        }
    });

这工作正常,但是一旦我尝试调用外部 REST 端点(我正在使用 Retrofit 和 Rx Observables),线程就在那里消失,永远不会调用端点,并且不再执行连续的命令。

我认为这与线程有关,例如当库在关闭时创建额外的线程时,JVM 似乎会杀死一切。

任何人都可以阐明或建议我还可以尝试什么吗?

--

补充信息:

我需要执行长运行宁清理。问题是我无法确定关闭信号的样子以及何时发生,因为 Docker 容器中的 JVM 运行s 在 docker stop 时(当主机停止时),首先发送 SIGTERM,然后在超时后(我可以设置,目前为 60 秒)SIGKILL。容器 运行s socket.io 中的 JVM,可能可以连接数千个客户端。我想用 60 秒向每个客户端发送一个 good-bye 并完全断开这些连接,并从负载均衡器中注销服务器。所以在清理过程中有很多潜在的阻塞操作。

如果Java认为清理总是很短,那么Java就错了:(

在您的案例中关闭 JVM 时会引发中断标志。因此,只要您调用任何阻塞操作,该操作就会立即被 InterruptedException 终止。

如果您必须在应用程序终止时执行进一步的、可能会持续很长时间的代码,那么关闭挂钩不是可行的方法。它的存在是为了关闭开放资源,而不是为了创建新资源。

由于您没有提供有关您的代码的更多信息,我无法给出确切的建议,但一般的想法是让主线程在应用程序 运行ning 时等待,并让主线程进行清理工作。然而,在这种情况下,您需要一个不是系统关闭信号的关闭信号,因此应用程序可以继续正常 运行。

如果由于某种原因这太复杂了,您可以尝试通过执行以下操作来清除关闭挂钩开头的中断标志:

try {
  Thread.sleep(1);
} catch (InterruptedException e) {
}

然而,这是违反规则的,而这些规则的存在是有原因的。 IE。 OS 如果您的程序对 kill 信号的反应不够快并以更糟糕的方式终止它,它可能会认为您的程序挂起。