Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 终止线程或异步任务_Java_Multithreading_Kotlin - Fatal编程技术网

Java 终止线程或异步任务

Java 终止线程或异步任务,java,multithreading,kotlin,Java,Multithreading,Kotlin,假设我使用IBM创建的jar。 假设这个Jar有一个我需要的功能,但最终是这样构建的: while (true) { System.out.println(1) } (当然,它实际上并不只是打印1,但举个例子,我们假设它是) 因此,我使用future调用了在另一个线程中执行此操作的函数。我如何才能完全杀死运行此代码的线程?或者,我如何终止Kotlin中运行代码的异步任务 Kotlin或Java的解决方案将非常好, 提前谢谢 编辑: 我发现,如果这是一个线程,我可以thread#s

假设我使用IBM创建的jar。 假设这个Jar有一个我需要的功能,但最终是这样构建的:

 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;
}