我正在使用以下测试代码测试InterruptedException:
Runnable runMe = new Runnable() {
@Override
public void run() {
for(int i=0; i<6; i++) {
System.out.println("i = "+i);
if(i==3) {
System.out.println("i==3, Thread = "
+Thread.currentThread().getId());
//I invoke interrupt() on the working thread.
Thread.currentThread().interrupt();
try {
Thread.currentThread().join();
} catch (InterruptedException e) {
//I caught InterruptedException
System.out.println(Thread.currentThread().getId()
+ " is interrupted!");
Thread.currentThread().interrupt();
}
}
}
}
};
Thread workingThread = new Thread(runMe);
workingThread.start();
try {
workingThread.join();
} catch (InterruptedException e) {
//Swallow
}
//the following log shows me workingThread.isInterrupted() is false, why?
System.out.println("workingThread("
+ workingThread.getId()+") interrupted ? "
+ workingThread.isInterrupted());
在run()
,我interrupt()
当前工作线程,并抓住了InterruptedException
。
在主线程中,我的最后一行代码是System.out.println(...)
,它打印出工作线程的中断状态。由于我在InterruptedException
中抓住了run()
,我虽然应该收到workingThread.isInterrupted()
true ,的消息,但我弄错了,为什么?< /强>
答案 0 :(得分:4)
Oracle的Java concurrency tutorial说(我强调补充):
中断状态标志
使用称为中断状态的内部标志实现中断机制。调用Thread.interrupt设置此标志。当线程通过调用静态方法Thread.interrupted来检查中断时,将清除中断状态。非静态isInterrupted方法,一个线程用来查询另一个线程的中断状态,不会改变中断状态标志。
按照惯例,通过抛出InterruptedException退出的任何方法都会在执行此操作时清除中断状态。但是,通过另一个调用中断的线程,总是可以立即再次设置中断状态。
你看到的是线程被中断,退出的方法是连接(实际连接是通过调用Object.wait来实现的,所以我希望stacktrace会显示wait是引发异常的方法来自),并且标志会像教程所说的那样被清除。
由异常的处理程序决定是否应该再次设置线程的中断状态标志。除非处理程序被编码为执行不同的操作,否则默认的假设是处理异常并且不再需要设置标志。
API documentation for Thread#interrupt与此一致:
如果在调用Object类的wait(),wait(long)或wait(long,int)方法,或者join(),join(long),join(long)时阻塞了这个线程,int),sleep(long)或sleep(long,int),这个类的方法,然后它的中断状态将被清除,它将收到InterruptedException。
我的答案更多地说明了为什么设计中断的原因here。
答案 1 :(得分:0)
Runnable runMe = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("i = " + i);
if (i == 3) {
System.out.println("i==3, Thread = "
+ Thread.currentThread().getId());
//I invoke interrupt() on the working thread.
Thread.currentThread().interrupt();
try {
Thread.currentThread().join();
} catch (InterruptedException e) {
//I caught InterruptedException
System.out.println(Thread.currentThread().getId()
+ " is interrupted!");
Thread.currentThread().interrupt();
}
}
}
}
};
Thread workingThread = new Thread(runMe);
workingThread.start();
Thread.sleep(1);
// output true, because child thread not deaded
System.out.println("workingThread("
+ workingThread.getId() + ") interrupted ? "
+ workingThread.isInterrupted());