关闭第三个应用程序线程而不等待其完成的首选方法是什么?



我目前正在运行无法更改的 JAR,有时它只是无缘无故地卡住。我尝试过找到中断线程、停止线程等的方法,但没有运气。

提供的每个解决方案都是关于执行完全退出或等待线程完成。

我想做的是简单地关闭线程,确切地说,超时完成,然后继续程序。

我不想做的是使用带有超时的while循环,java.util.concurrent.Future,System.exit,并进行Thread.interrupt调用。

这些都无济于事!

您不能在执行过程中强制停止线程。Thread.destroy()方法本可以做到这一点,但它从未实现过,其文档解释了为什么即使它有效也不安全。

还有其他一些不推荐使用的方法,如Thread.stop()Thread.suspend(),它们可能实际上有效,但它们使用起来也不安全;同样,他们的文档解释了原因。

告诉线程它应该自行终止,然后等待它这样做,是停止线程的唯一安全方法。


作为一种解决方法,您可以在一个完全独立的进程中运行任务,以便在希望它停止时可以销毁它。这是安全的,因为进程彼此隔离,销毁子进程不会使父进程处于不稳定状态。

但是,与单独的进程交互更加困难,因为您无法像与线程交互那样在进程之间共享变量。 您需要通过流程的输入和输出流发送消息。

实际上,你真的无法解决这个问题!

我的意思是:即使您设法杀死用于触发第三方代码的"您的"线程 - 您也无法杀死由您正在调用的代码创建的线程或进程。

如果你想绝对确定杀死所有的东西,你可能不得不研究相当复杂的解决方案,例如:

  • 您不是只使用线程,而是使用新的 JVM B 创建新进程
  • 在该 JVM B 中,您可以调用该库
  • 但是,当然,这需要你放置额外的代码;这样JVM A中的"你的"代码就可以与JVM B中的"你的"代码通信。
  • 现在,您也许可以拆除该过程以及属于它的所有工件。或。

说真的:要真正确定第三方库没有踢任何你不能停止的东西;你甚至可能必须在某种容器(例如docker实例)中运行该JVM。你可以拆掉并确保一切都消失了。

长话短说:我认为没有办法绝对控制线程中创建的线程。如果您需要这种级别的控制,您需要考虑"外包"这些呼叫。

您可以使用Executor。它允许您submit任务(例如runnable),并并行执行这些任务。此外,一旦您调用shutdown(),它允许您配置超时,并在那时尚未完成所有工作线程时杀死它们。示例如下所示:

ExecutorService executor = Executors.newFixedThreadPool(1);
executor.execute(() -> {
//logic to call the method of third party jar
});
//Other business logic
executor.awaitTermination(1, TimeUnit.MINUTES);
executor.shutdownNow();

TimeUnit是一个枚举,具有SECONDSHOURSMINUTES等值(这里是 javadoc),因此您可以配置不同的时间单位。几点:

  • 调用shutdownNow后,将不接受任何新任务(即不能调用executesubmit),并且将停止现有任务。因此,我们基本上是在等待一分钟任务完成,如果任务没有完成,我们就在扼杀该任务。
  • awaitTermination抛出InterruptedException(因为如果线程未完成,它会在内部中断线程),因此您必须将其包装在块try-catch内。

这是 Executor 的 javadoc。

最新更新