假设我有类似的课程: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()(从Internet上学习)从Runnable内部中断线程时,我认为我想停止在Runnable的方法中调用此方法,然后在另一个Thread的实例中调用此方法会打断它。但是如上面的示例所示,它正在中断调用该方法的线程,而不是运行定义该方法的Runnable的线程。知道我对Thread.currentThread.interrupt()的工作方式一无所知,并且无法正常工作时,我有几个问题:1.从本示例的工作方式来看,我假设Thread.currentThread.interrupt()中断了正在执行调用该函数的线程的线程,而不是正在运行该函数调用其实例的线程。那正确吗?如果没有,它如何运作?2.(最重要的)是否可以通过从另一个线程调用其Runnable的方法来中断线程?如果是,怎么办?如果不是-我是否必须访问Thread实例才能中断它,或者如果Foo只是扩展Thread而不是实现Runnable会更好?3.如果在睡眠之前调用了中断,为什么会捕获到Bar的异常?
要尝试完全回答您的问题:
您是对的。如您所见,https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html Thread.currentThread()
返回对当前执行线程的引用。
因为按照您在1.中的建议,您正在中断当前正在执行的线程,该线程是Bar
上下文所在的线程。Bar
导致了它自己的InterruptedException
。
Thread.currentThread()
返回当前正在运行的线程。您似乎期望与Thread.currentThread()
实例相关联的线程,因为其Foo
方法几乎占据了整个类,因此run()
方法将使用该线程,但是terminate()
为只是一个普通的班级。它的Foo
方法可以由已使用其实例启动的其他线程调用,也可以直接调用。无论如何,当直接在某个线程上调用run()
方法时,terminate()
将返回该线程。
Thread.currentThread()
方法不一定会引发thread.interrupt()
。如果线程正在休眠,等待或调用某些阻止操作,则会发生这种情况,但是文档中说:
如果以上条件均不成立,则将设置该线程的中断状态。
中断状态只是一个标志,指示线程已被中断。下次调用睡眠,等待或阻止操作时,将立即抛出thread.interrupt()
。
如果要中断特定线程而不是当前线程,特别是对于已启动的线程,则有一个简单的解决方案:在启动线程时存储对该线程的引用。
InterruptedException
然后在InterruptedException
中,而不是调用Thread fthread = new Thread(f).start();
Bar b = new Bar(f, fthread);
,而是调用Bar
。