使用其方法中断Runnable实例

时间:2019-09-25 18:47:10

标签: java multithreading interrupt runnable

比方说,我有类似的课程: Foo.java:

public class Foo implements Runnable{
  public void run(){
    try{
      sleep(3000);
      System.out.println("Slept for 3s");
    }catch(InterruptedException e){
      Thread.currentThread().interrupt();
      System.out.println("Exception handled from Foo");
    }
  }

  public void terminate(){
    Thread.currentThread().interrupt();
  }
}

Bar.java:

public class Bar implements Runnable{
  private Foo f;

  public Bar(Foo f){
    this.f = f;
  }

  public void run(){
    System.out.println("Interrupting Foo");
    f.terminate();
    System.out.println("Interrupted Foo");
    try{
      sleep(4000);
      System.out.println("Slept for 4s");
    }catch(InterruptedException e){
      Thread.currentThread().interrupt();
      System.out.println("Exception handled from Bar");
    }
  }
}

Test.java:

public class Test{
  public static void main(String[] args){
    Foo f = new Foo();
    Bar b = new Bar(f);
    new Thread(f).start();
    new Thread(b).start();
    System.out.println("Test end");
  }
}

当我编写此代码时,我希望输出如下:

Test end
Interrupting Foo
Exception from Foo handled
Interrupted
Slept for 4s

但我没有得到上面的东西:

Test end
Interrupting Foo
Interrupted
Exception from Bar handled
Slept for 3s

此代码背后的故事是,在我的应用程序中,我需要一个线程/可运行对象来中断另一个运行我可以访问的可运行实例的匿名线程。知道我可以使用Thread.currentThread.interrupt()从Runnable内部中断线程(从Internet上学习),我认为我想停止在Runnable的方法中调用此方法,然后在另一个Thread的实例中调用此方法会打断它。但是如上面的示例所示,它正在中断调用该方法的线程,而不是运行定义该方法的Runnable的线程。知道我对Thread.currentThread.interrupt()的工作方式一无所知,并且无法正常工作时,我有几个问题:
1.从本示例的工作方式来看,我假设Thread.currentThread.interrupt()中断了正在执行调用该函数的线程的线程,而不是正在运行该函数调用其实例的线程。那正确吗?如果没有,怎么办?
2.(最重要的)是否可以通过从另一个线程调用其Runnable的方法来中断线程?如果是,怎么办?如果不是-我是否必须访问Thread实例才能中断它,或者如果Foo只是扩展Thread而不是实现Runnable会更好吗?
3.如果在睡眠之前调用了中断,为什么会捕获到Bar的异常?

2 个答案:

答案 0 :(得分:0)

尝试完全回答您的问题:

  1. 您是对的。如您所见,https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html Thread.currentThread()返回对当前正在执行的线程的引用。

  2. 是的。 Android: How do I stop Runnable?

  3. 因为您在1.中建议,所以您正在中断当前正在执行的线程,该线程是Bar上下文所在的线程。Bar导致了它自己的InterruptedException

答案 1 :(得分:0)

Thread.currentThread()返回当前正在运行的线程。您似乎期望有一个与Foo实例相关联的线程,因为它的run()方法几乎占据了整个类,然后它的terminate()方法将使用该线程,但Foo只是一个普通的类。它的run()方法可以由已从其实例启动的其他线程调用,也可以直接调用。无论如何,当在某个线程上直接调用terminate()方法时,Thread.currentThread()将返回该线程。

thread.interrupt()方法不一定会引发InterruptedException。如果线程正在休眠,等待或调用某些阻止操作,则会发生这种情况,但是文档说:

  

如果以上条件均不成立,则将设置此线程的中断状态。

中断状态只是一个标志,指示线程已被中断。下次调用睡眠,等待或阻止操作时,InterruptedException将立即抛出。

如果要中断特定线程而不是当前线程(特别是对于已启动的线程),则有一个简单的解决方案:在启动线程时存储对该线程的引用。

Thread fthread = new Thread(f).start();
Bar b = new Bar(f, fthread);

然后在Bar中,而不是呼叫f.terminate(),而是呼叫fthread.interrupt()