我想知道为什么似乎不支持线程级' shutdown hooks',它在特定线程终止时运行;当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接受最后一个套接字并返回
湾发送到intterupt serverSocket.accept的中断
在上述任何一种情况下,我们都希望运行shutdownLogic方法,假设它只是关闭seversocket做一些事情,一些外部源接口,无论线程如何关闭都很重要。
据我了解,这不是很容易做到,事实上我觉得我必须缺少一些基本的线程功能似乎很难。 1a案例很简单,按原样运作。只要开发人员没有吞下interruptExceptions就可以使用1b的情况,这种情况经常发生,但如果你知道中断异常是什么就很容易避免。
如果出现异常,您需要将关闭方法移动到finally块中。
案例3& 4虽然这变得更难。对于3我认为线程可以很好地被杀死,有一个人可以捕获的中断,检查它是否有一个sigkill,然后强制退出代码,但这需要更加智能处理最不正确吞下的InterruptException;如果必须在可以通过中断的几十个位置进行此检查,加上会变得很难看。你不能为一次硬杀人做太多事情,但是没有人期望有适当的关闭逻辑来进行硬杀,所以这很好。
对于JVM关闭...我实际上并不知道线程被杀死的确切方法。我假设在硬杀之前将一个sigkill发送到线程超时,我必须更多地研究它。如果你想要安全,你可以添加一个关闭钩子,但是没有关于运行关闭钩子的命令,并且尝试为每个线程添加关闭钩子需要仔细写入钩子以确保你不会停止或通过挂钩中的死锁或意外异常来停止JVM关闭....
如果不是像上面那样的线程,我有一个有限但可能很长的处理时间的线程,没有任何等待,它变得更难,因为我无法监听中断的异常以便知道我需要放弃我的线程处理并立即运行关闭逻辑。
基本上,似乎需要使用不同的方法来处理线程可以执行的每种方式,并且需要在每个线程中完成。仍然在高CPU线程无需等待的情况下,如果线程(而不是整个JVM)在中途被杀死,我现在仍然不知道如何正确关闭...
对所有这些都没有更简单的解决方案吗?例如,相当于一个线程级别的关闭钩子,它将在该特定线程被杀死时运行,无论它如何死亡;即使JVM本身没有关闭?是否存在某种原因线程级别shutdownhook是不可能或不支持的,假设这种情况不存在。
答案 0 :(得分:2)
至少有一个原因是确实没有一个安全和清洁的机制,这也是为什么Thread.stop()被弃用的原因。通过为它创建一个(看似简单的)简单机制,人们可能会认为这是一个简单的问题并且大量使用它。
终结器和shutdownhooks存在同样的问题。它们不可靠,所以让开发人员认为它是他们应该使用的普通工具并不是一个好主意。
答案 1 :(得分:0)
是的,Java提供了这样一种机制。如果您使用run()
,只需在Thread
子类中使用Runnable
方法或Runnable
中使用try / finally结构:
public void run() {
try {
doBody()
}
finally {
doThreadShutdown()
}
}
这应该处理您正在寻找的所有情况,包括虚拟机的正常关闭,因为虚拟机仅在所有非守护程序线程退出后关闭。例外是线程的硬停止,虚拟机的硬件杀死,或者线程是守护程序线程并且虚拟机退出。