Java 终止线程或异步任务
假设我使用IBM创建的jar。 假设这个Jar有一个我需要的功能,但最终是这样构建的:Java 终止线程或异步任务,java,multithreading,kotlin,Java,Multithreading,Kotlin,假设我使用IBM创建的jar。 假设这个Jar有一个我需要的功能,但最终是这样构建的: while (true) { System.out.println(1) } (当然,它实际上并不只是打印1,但举个例子,我们假设它是) 因此,我使用future调用了在另一个线程中执行此操作的函数。我如何才能完全杀死运行此代码的线程?或者,我如何终止Kotlin中运行代码的异步任务 Kotlin或Java的解决方案将非常好, 提前谢谢 编辑: 我发现,如果这是一个线程,我可以thread#s
while (true) {
System.out.println(1)
}
(当然,它实际上并不只是打印1,但举个例子,我们假设它是)
因此,我使用future调用了在另一个线程中执行此操作的函数。我如何才能完全杀死运行此代码的线程?或者,我如何终止Kotlin中运行代码的异步任务
Kotlin或Java的解决方案将非常好,
提前谢谢
编辑:
我发现,如果这是一个线程,我可以
thread#stop()
it使它真正停止。但不幸的是,使构造函数多次抛出异常会导致JVM从内存中删除该类,从而导致下次实例化该类时出现NoClassDefFoundError
如果您可以捕获它的线程,那么只要它在内部执行某种阻塞功能,您就应该能够杀死它
class OtherFunction implements Runnable {
@Override
public void run() {
while(true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// We assume the thread will exit when interrupted.
System.out.println("Bye!!");
return;
}
System.out.println("Hello");
}
}
}
class Killable implements Runnable {
final Runnable target;
private Thread itsThread;
Killable(Runnable target) {
this.target = target;
}
@Override
public void run() {
// Catch the thread id of the target.
itsThread = Thread.currentThread();
// Launch it.
target.run();
}
public void kill() {
// Give it a good kick.
itsThread.interrupt();
}
}
public void test() throws InterruptedException {
OtherFunction theFunction = new OtherFunction();
Killable killableVersion = new Killable(theFunction);
new Thread(killableVersion).start();
// Wait for a few seconds.
Thread.sleep(10000);
// Kill it.
killableVersion.kill();
}
似乎Thread#stop()
解决了我的问题。我知道它已经被弃用了,可以通过catch(Throwable t)
来防止,但至少它对我起到了作用
顺便说一下,为了从执行器获取线程,我使用了AtomicReference
,并在回调中设置它 Thread#stop()
被视为“天生不安全”,应尽可能避免使用
这是不稳定和腐败的根源,而且可能会失败
它实际上会导致在目标线程中抛出一个ThreadDeath
异常。
无论它出现在什么代码中,其作者都不太可能预料到这一结果。
对象可能处于不一致的状态,外部资源可能被占用并泄漏,文件可能未完全写入
有一些方法可以处理意外错误,但实际上,大多数代码都是在假定知道可能抛出哪些异常的情况下编写的,而不是在预料到会出现这种“意外”的情况下编写的
给定ThreadDeath
是一个Throwable
任何catch(Throwable t)
都会一次又一次地捕捉它,除非对线程可能执行的每一段代码都非常小心(不切实际)ThreadDeath
可能只是被吸收而不是结束线程
正确的处理方法是声明一个原子变量(通常作为表示任务的Runnable
的一部分)
AtomicBoolean stopThread=new AtomicBoolean(false);
然后将循环编写为:
while (!stopThread.get()) {
System.out.println(1);
}
并提供一种方法:
public void stopThread(){
stopThread.set(true);
}
或者,您可以使用interrupt()
并选中interrupted()
。这些是Thread
类中提供的更干净的方法。interrupted()
在调用时具有清除标志的行为。这并不总是有帮助,而Thread.currentThread().isInterrupted()可以检查标志
checking the flag clears it(检查标志清除它)行为可能没有帮助,并且还会遇到一些问题,如stop()
,因为它可能会导致在其他代码从未预料到的点抛出“意外”异常。正确的方法是使用您自己的标志,并完全控制流程决定退出的位置
你挑吧
另见:
你有没有想过,为什么当你点击某个并发进程上的“取消”按钮时,你常常要等它响应很久? 这就是为什么。任务需要到达一个定义明确的点,并进行任何必要的清理,以一种定义明确的方式结束 把
Thread#stop()
想象成把自行车手踢下自行车来阻止他们。这里的方法是向他们挥舞红旗,然后他们以最快的速度安全地停下来
Thread#stop()
不应该使用Java,也不应该使用它。
在开发和小型系统中,您可以不受影响。它会在大型生产环境中造成严重破坏。
它不仅仅被弃用为“不推荐”,它是“固有的不安全”,不要使用它。
它已经被弃用多年了,令人失望的是,一些“删除日期”从未被宣传过
下面是一个使用Thread#stop()
或interrupt()
的示例,具体取决于您是否选择危险
import java.lang.System;
import java.lang.Thread;
class Ideone
{
private static boolean beDangerous=true;//Indicates if we're going to use the Thread#stop()....
//This main method uses either stop() or interrupt() depending on the option.
public static void main (String[] args) throws java.lang.Exception
{
PrimeFactor factor=new PrimeFactor();
try{
for(int i=1;i<30;++i){
Thread thrd=new Thread(new Primer(factor));
thrd.start();
Thread.sleep(10);//Represents some concurrent processing...
if(beDangerous){
thrd.stop();
}else{
thrd.interrupt();
}
thrd.join();
if(!factor.check()){
System.out.println("Oops at "+i);
}
}
}catch(Throwable t){
System.out.println(t);
}
}
//This class just hammers the PrimeFactor object until interrupt()ed (or stop()ed).
private static class Primer implements Runnable {
private PrimeFactor factor;
public Primer(PrimeFactor ifactor){
factor=ifactor;
}
public void run(){
int i=1;
while(!Thread.interrupted()){
factor.set(i++);
}
}
}
//Don't worry about this bit too much.
//It's a class that does a non-trivial calculation and that's all we need to know.
//"You're not expected to understand this". If you don't get the joke, Google it.
//This class calculates the largest prime factor of some given number.
//Here it represents a class that ensures internal consistency using synchronized.
//But if we use Thread#stop() this apprently thread-safe class will be broken.
private static class PrimeFactor {
private long num;
private long prime;
public static long getFactor(long num){
if(num<=1){
return num;
}
long temp=num;
long factor=2;
for(int i=2;temp!=1;++i){
if(temp%i==0){
factor=i;
do{
temp=temp/i;
}while(temp%i==0);
}
}
return factor;
}
public synchronized void set(long value){
num=value;
prime=getFactor(value);
}
public synchronized boolean check(){
return prime==getFactor(num);
}
}
}
请注意,PrimeFactor
类可以被描述为线程安全的。它的所有方法都是同步的
。想象一下它在某个库中。期望“线程安全”意味着线程#停止()
安全是不现实的,唯一的方法是侵入性的。将对它的调用放入try catch(ThreadDeath tde)中
block无法修复任何东西。在它被捕获之前,损坏已经被消除
不要让自己相信将set()
更改为以下选项可以解决问题:
public synchronized void set(long value){
long temp=getFactor(value);
num=value;
prime=temp;
}
首先也是最重要的一点是,ThreadDeath
异常可能会在分配过程中抛出,因此所做的只是潜在地缩短比赛条件下的赔率。它没有被否定。永远不要说“发生这种情况的可能性有多大”关于种族条件的争论。程序调用方法几十亿次,所以十亿分之一的机会经常出现
要使用
Thread#stop()
您基本上永远不能使用任何库对象,包括java.*
和跳转来处理ThreadDeath
代码中的任何地方,并且几乎肯定最终会失败。您是否准备在执行时更改(true)
condition?你说你有future
。调用future#cancel(true)
?有什么问题吗?@AmitBera没有,我不能触摸执行它的函数中的代码。@rkosegi我确实调用了它,我甚至调用了ExecutorService#shutdownNow()函数,但它们都不能杀死线程。thread#stop()
是您唯一的选择,但它a)是一个蹩脚、泄漏的机制,可能会破坏整个应用程序的稳定性,b)可能仍然无法终止线程,因为它所做的只是在线程中抛出异常。我不确定这是否有助于OP在这种情况下:
public synchronized void set(long value){
long temp=getFactor(value);
num=value;
prime=temp;
}