我目前正在运行无法更改的 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
是一个枚举,具有SECONDS
、HOURS
、MINUTES
等值(这里是 javadoc),因此您可以配置不同的时间单位。几点:
- 调用
shutdownNow
后,将不接受任何新任务(即不能调用execute
或submit
),并且将停止现有任务。因此,我们基本上是在等待一分钟任务完成,如果任务没有完成,我们就在扼杀该任务。 awaitTermination
抛出InterruptedException
(因为如果线程未完成,它会在内部中断线程),因此您必须将其包装在块try-catch
内。
这是 Executor 的 javadoc。