6

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

甲类:

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 循环,共享变量将无效。

任何的想法 ?提前致谢。

4

5 回答 5

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

然后,如果有人调用runEverythingon BB则可以调用cancelon A(您将不得不提取A变量,以便B 即使在runEverything调用之后也要引用它。

于 2012-08-11T01:36:31.683 回答
3

我认为你应该坚持使用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.        
}

这等效于声明和使用您自己的“终止开关”变量,除了:

  • 同步API很多,有些I/O API关注interrupted状态,
  • 一个乖巧的 3rd 方库会关注interrupted状态。

现在确实有很多代码处理不当 InterruptedException;例如通过挤压它。(处理 an 的正确方法InterruptedException是允许它传播,或者调用Thread.interrupt()以再次设置标志。)但是,另一方面是相同的代码不会知道您的终止开关。所以无论哪种方式你都有问题。

于 2012-08-11T03:15:51.387 回答
1

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

于 2012-08-11T01:35:59.887 回答
0

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

1) 不要停止它 - 用 Interrupted 标志发出信号停止,将其优先级设置为尽可能低,并“孤立”线程和它正在处理的任何数据对象。如果您需要再次执行此线程执行的操作,请进行另一个操作。

2) 清空、损坏、重命名、关闭或以其他方式破坏正在处理的数据,以强制线程进行段错误/AV 或以其他方式除外。线程可以捕获抛出并检查中断标志。

没有保证,如所见即卖...

于 2012-08-11T04:07:43.513 回答
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() 的状态。

于 2019-03-27T05:00:43.767 回答