如何终止Java中的持久线程? [复制]

Posted

技术标签:

【中文标题】如何终止Java中的持久线程? [复制]【英文标题】:How to terminate a persistent thread in Java? [duplicate] 【发布时间】:2021-04-05 23:05:48 【问题描述】:

我想创建一个线程来判断用户代码:

FutureTask<Integer> futureTask = new FutureTask(() -> run(type));  // run is a method
Thread thread = new Thread(futureTask);
thread.start();

众所周知,用户代码中可能会写死循环,所以run方法会一直工作,而线程thread不会停止。我想在超时时间后终止这个thread。我怎样才能终止它而不是使用Thread.stop,因为它不安全?

【问题讨论】:

使用进程怎么样?如果你使用一个线程,它可能非常不安全,因为你的线程和用户的线程在同一个地址空间中。 我正在考虑,因为如果我使用一个进程,我需要更改很多代码。 【参考方案1】:

处理需要停止的线程的正确方法是设计线程的代码,使其对被中断做出适当的响应:

长时间计算需要偶尔检查当前线程的“中断”标志。

InterruptedException 应妥善处理。

线程应用程序代码对中断的响应应该是优雅地停止它正在执行的操作1并(通常)允许线程终止。

(您也可以使用使用volatile 共享变量而不是中断标志实现的自定义标志。但是,这不处理中断waitsleep 和类似操作,因此是一个差代替中断。)


不安全的方法是调用已弃用的Thread.stop() 方法。 (javadocs 解释了为什么它不安全,我们不需要在这里重复。)

(相关的)Thread.stop(Throwable) 方法在 Java 11 中被删除;见:

Java 11 Removes stop() and destroy() Methods.

https://bugs.openjdk.java.net/browse/JDK-8204243


不幸的是,这两种中断线程的方法之间没有任何区别。

如果你不能让你的长时间运行的线程合作,安全的选择是在一个单独的进程中运行它;例如使用System.ProcessBuilder 等运行java 命令。如果花费的时间太长,则(外部)进程可能会被终止。缺点包括:

外部进程无法访问当前 JVM 的变量等。所以你需要使用不同的机制在父子进程之间传递信息。

启动一个新的 JVM 比启动一个新线程要昂贵得多。


1 - 例如,如果线程拥有资源,如打开的文件或套接字,它应该释放它们。如果它正在为等待结果的其他线程执行操作,它应该(以适当的方式)发出没有结果的信号。以此类推。

【讨论】:

哦,对不起。也许我错过了一些重要的事情。其实run方法会调用一个C写的native方法。这个navtive方法会启动一个新的线程来判断用户代码util它返回的结果。一旦无限循环出现在用户代码中,它就无法返回。我可以终止 Java 中的线程并使 C 中的子线程终止吗?如果是的话,你能告诉我怎么做吗? 没有直接的解决方案。即使使用Thread.stop() 也不起作用,因为它不会杀死您在本机代码中启动的线程。请注意,终止本机线程与停止或销毁 Java 线程具有相同的问题。见***.com/questions/2084830/… 这个问题的最佳解决方案可能是在单独的 JVM/外部进程中运行用户代码。您可以使用Process.destroy() 对其进行管理。 谢谢,我会考虑使用Process,这可能会改变很多代码。【参考方案2】:

从外部终止线程总是不安全的,强烈建议不要这样做。您需要通知线程您希望它终止并且线程必须自己完成。这是通过类 Thread 的方法 interrupt() 完成的。在您的示例中,它将从主代码调用thread.interrupt() 这将导致在您的线程中引发中断标志。在您的线程的run 方法中,您应该检查该标志(参见Thread 类中的方法interrupted()isInterrupted())。一旦你看到你的标志被升起,就跳出循环并完成该方法。这将停止你的线程。

【讨论】:

以上是关于如何终止Java中的持久线程? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

Java并发编程-如何终止线程

c++11的线程,怎么终止

如何正确停止线程

并发编程——如何终止线程

[编程][JAVA]在JAVA中如何终止线程中socket.accpet() ? 端口一直被占用

java 线程的终止与线程中断