立即停止线程

时间:2012-08-11 01:24:55

标签: java multithreading

我想立即停止正在运行的线程。这是我的代码:

A类:

public class A() {
    public void methodA() {
        For (int n=0;n<100;n++) {
        //Do something recursive
        }
        //Another for-loop here

        //A resursive method here

        //Another for-loop here

        finishingMethod();        
    }    
}

B组:

public class B() {
    public void runEverything() {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                    A a = new A();
                    a.methodA();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
       Thread thread = new Thread(runnable);
       thread.start();
    }

我的问题是我需要能够在线程完成之前在B类中停止线程。我已经尝试过interrupt()方法,但这并没有阻止我的线程。我也听说过使用共享变量作为一个信号来阻止我的线程,但我认为在我的进程中使用长递归和for循环,共享变量将不会有效。

有什么想法吗? 提前谢谢。

5 个答案:

答案 0 :(得分:13)

Thread.interrupt不会停止你的线程(除非它处于睡眠状态,在这种情况下会抛出InterruptedException)。中断基本上会向线程发送一条消息,指示它已被中断,但它不会导致线程立即停止。

当您进行长循环操作时,使用标志来检查线程是否已被取消是一种标准方法。您可以修改methodA以添加该标志,例如:

// this is a new instance variable in `A`
private volatile boolean cancelled = false;

// this is part of your methodA
for (int n=0;n<100;n++) {
  if ( cancelled ) {
    return; // or handle this however you want
  }    
}

// each of your other loops should work the same way

然后可以添加取消方法来设置该标志

public void cancel() {
  cancelled = true;   
}

如果有人在runEverything上拨打BB就可以在cancel上拨打A(您必须提取A变量使得B即使在调用runEverything后也会引用它。

答案 1 :(得分:2)

我认为你应该坚持使用Thread.interrupt()。但是,要使其工作,您需要做的是更改methodA代码以执行以下操作:

public void methodA() throws InterruptedException {
    for (int n=0; n < 100; n++) {
        if (Thread.interrupted) {
             throw new InterruptedException();
        }
        //Do something recursive
    }
    // and so on.        
}

这相当于声明并使用你自己的“kill switch”变量,但是:

  • 许多同步API,一些I / O API关注interrupted状态和
  • 一个表现良好的第三方库会关注interrupted州。

现在确实有很多代码错误处理 InterruptedException;例如通过挤压它。 (处理InterruptedException的正确方法是允许它传播,或者调用Thread.interrupt()再次设置标志。)然而,反面是相同的代码不会意识到你的杀戮开关。无论如何你都有问题。

答案 2 :(得分:1)

您可以检查运行标志的状态,作为循环或递归的一部分。如果有一个kill信号(即run flag设置为false),只需返回(在你需要进行任何清理之后)。

答案 3 :(得分:0)

还有其他一些可能的方法:

1)不要停止它 - 用“中断”标志发出信号停止,将其优先级设置为最低可能,然后“孤立”线程及其正在处理的任何数据对象。如果您需要再次执行此线程所执行的操作,请再创建一个。

2)将其正在处理的数据空出,损坏,重命名,关闭或以其他方式销毁以强制线程进行segfault / AV或以其他方式除外。线程可以捕获throw并检查Interrupted标志。

没有保证,按原样出售......

答案 4 :(得分:0)

从主线程开始letvsay someTask()被调用,并且t1.interrput被调用..

t1.interrupt();

    }

    private static Runnable someTask(){
        return ()->{



            while(running){
                try {
                    if(Thread.interrupted()){
                        throw new InterruptedException(  );
                    }
               // System.out.println(i + " the current thread is "+Thread.currentThread().getName());


                  //  Thread.sleep( 2000 );
                } catch (Exception e) {

                    System.out.println(" the thread is interrputed "+Thread.currentThread().getName());
                    e.printStackTrace();
                    break;
                }
            }

o / P:

java.lang.InterruptedException
    at com.barcap.test.Threading.interrupt.ThreadT2Interrupt.lambda$someTask$0(ThreadT2Interrupt.java:32)
    at java.lang.Thread.run(Thread.java:748)
 the thread is interrputed Thread-0

t1.interuuption是不够的。这需要检查子线程中Thread.interrupted()的状态。