【发布时间】:2016-07-28 16:26:55
【问题描述】:
我想知道为什么似乎不支持线程级别的“关闭挂钩”,它在特定线程终止时运行; 不当JVM终止时。
假设有人用这样的 sudo 代码编写了一个带有 run 方法的简单线程(暂时在这里故意省略线程中断......):
public void run(){
SeverSocket serverSocket=new ServerSocket(port);
while(!isStopRequested){
Socket socket=serverSocket.accept();
processRequest(socket);
}
runShutdownLogic();
}
public void stopServer(){
isStopRequested=false;
//interrupt thread potentially, see below
}
这个线程可能会以几种方式死掉:
-
有人调用 stopServer,然后是...
一个。 serversocket.accept 接受最后一个套接字并返回
b.发送到中断 serverSocket.accept 的中断
- 抛出异常
- 有人直接或通过执行器服务杀死了线程。
- JVM 出现故障。
在任何这些情况下,我们都想运行 shutdownLogic 方法,假设它比关闭 seversocket 做更多的事情,一个与外部源的接口,无论线程如何关闭都很重要。
据我了解,这并不容易做到,事实上,我觉得我必须缺少一些基本的线程功能,这似乎已经够难了。 1a 案例很简单,可以按原样工作。只要开发人员不吞下中断异常,1b 案例就可以工作,这种情况经常发生,但如果您知道什么是中断异常,就很容易避免。
如果发生异常,您需要将关闭方法移动到 finally 块中。
在案例 3 和 4 中,这会变得更难。对于 3,我认为线程可以“很好地”被杀死,一个可以捕获的中断,检查它是否是一个 sigkill,然后强制退出代码,但这需要更智能地处理最不恰当地吞下的 InterruptException ;如果必须在几十个可以通过中断的位置进行此检查,plus 会很快变得丑陋。你不能为硬杀做太多事情,但没有人期望为硬杀提供适当的关闭逻辑,所以这很好。
对于 JVM 关闭...我实际上并不知道线程被杀死的确切方法。我假设在硬杀之前将 sigkill 发送到超时的线程,我必须对其进行更多研究。如果你想安全,你可以添加一个关闭钩子,但是没有运行关闭钩子的顺序,尝试为每个线程添加关闭钩子需要仔细编写钩子以确保你不会停止或停止JVM 因死锁或钩子中的意外异常而关闭....
如果不是像上面那样的线程,我有一个处理时间有限但可能很长的线程,没有任何等待,它会变得更加困难,因为我无法监听中断的异常来知道我需要放弃我的线程处理并立即运行关闭逻辑。
基本上,似乎需要不同的方法来处理线程可以执行的每种方式,并且需要对每个线程进行处理。并且仍然在没有等待的高 CPU 线程的情况下,我现在仍然不知道如果线程(不是整个 JVM)在中途被杀死,如何正确关闭......
难道没有更简单的解决方案来解决所有这些问题吗?例如,相当于一个线程级关闭钩子,它将在该特定线程被杀死时运行,而不管它是如何死亡的;即使JVM本身没有关闭?假设不存在线程级shutdownhook,是否有某种原因无法支持或支持危险。
【问题讨论】:
标签: java multithreading