【问题标题】:Does java provide a clean mechanism for ensuring thread shutdown logic runs when thread dies?java是否提供了一种干净的机制来确保线程死亡时线程关闭逻辑运行?
【发布时间】: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
 }

这个线程可能会以几种方式死掉:

  1. 有人调用 stopServer,然后是...

    一个。 serversocket.accept 接受最后一个套接字并返回

    b.发送到中断 serverSocket.accept 的中断

  2. 抛出异常
  3. 有人直接或通过执行器服务杀死了线程。
  4. JVM 出现故障。

在任何这些情况下,我们都想运行 shutdownLogic 方法,假设它比关闭 seversocket 做更多的事情,一个与外部源的接口,无论线程如何关闭都很重要。

据我了解,这并不容易做到,事实上,我觉得我必须缺少一些基本的线程功能,这似乎已经够难了。 1a 案例很简单,可以按原样工作。只要开发人员不吞下中断异常,1b 案例就可以工作,这种情况经常发生,但如果您知道什么是中断异常,就很容易避免。

如果发生异常,您需要将关闭方法移动到 finally 块中。

在案例 3 和 4 中,这会变得更难。对于 3,我认为线程可以“很好地”被杀死,一个可以捕获的中断,检查它是否是一个 sigkill,然后强制退出代码,但这需要更智能地处理最不恰当地吞下的 InterruptException ;如果必须在几十个可以通过中断的位置进行此检查,plus 会很快变得丑陋。你不能为硬杀做太多事情,但没有人期望为硬杀提供适当的关闭逻辑,所以这很好。

对于 JVM 关闭...我实际上并不知道线程被杀死的确切方法。我假设在硬杀之前将 sigkill 发送到超时的线程,我必须对其进行更多研究。如果你想安全,你可以添加一个关闭钩子,但是没有运行关闭钩子的顺序,尝试为每个线程添加关闭钩子需要仔细编写钩子以确保你不会停止或停止JVM 因死锁或钩子中的意外异常而关闭....

如果不是像上面那样的线程,我有一个处理时间有限但可能很长的线程,没有任何等待,它会变得更加困难,因为我无法监听中断的异常来知道我需要放弃我的线程处理并立即运行关闭逻辑。

基本上,似乎需要不同的方法来处理线程可以执行的每种方式,并且需要对每个线程进行处理。并且仍然在没有等待的高 CPU 线程的情况下,我现在仍然不知道如果线程(不是整个 JVM)在中途被杀死,如何正确关闭......

难道没有更简单的解决方案来解决所有这些问题吗?例如,相当于一个线程级关闭钩子,它将在该特定线程被杀死时运行,而不管它是如何死亡的;即使JVM本身没有关闭?假设不存在线程级shutdownhook,是否有某种原因无法支持或支持危险。

【问题讨论】:

标签: java multithreading


【解决方案1】:

是的,Java 提供了这样的机制。只需在 run() 方法中使用 try/finally 构造,在 Thread 子类或 Runnable 中使用 Runnable

public void run() {

    try {
        doBody()
    }
    finally {
        doThreadShutdown()
    }
}

这应该会处理您正在寻找的所有情况,包括虚拟机的正常关闭,因为虚拟机仅在所有非守护线程退出后才会关闭。异常可能是线程的硬停止、虚拟机的硬终止,或者线程是守护线程并且虚拟机退出。

【讨论】:

    【解决方案2】:

    至少其中一个原因是确实没有安全和干净的机制,这也是不推荐使用Thread.stop() 的原因。通过为它创建一个(看似)简单的机制,人们可能会认为这是一个简单的问题并疯狂地使用它。

    终结器和关闭挂钩也存在同样的问题。它们不可靠,因此让开发人员认为这是他们应该使用的普通工具并不是一个好主意。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-22
      • 1970-01-01
      • 1970-01-01
      • 2011-06-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多