while循环中断异常vs isInterrupted

时间:2013-02-19 08:57:11

标签: java multithreading concurrency while-loop interrupted-exception

假设我有以下代码:

while(!Thread.currentThread().isInterrupted()){  
    //do something   
    Thread.sleep(5000);  
}

现在Thread.sleep会抛出`InterruptedException,所以它应该是这样的:

while(!Thread.currentThread().isInterrupted()){  
   //do something   
   try{  
     Thread.sleep(5000);    
   } catch(InterruptedException e){  

   }
}

如果我点击catchwhile循环会继续,还是我需要Thread.currentThread().interrupt()?如果我确实调用了这种方法,那么这也不会导致InterruptedException吗?否则我是如何得到例外的?

如果我有:

while (!Thread.currentThread().isInterrupted()){  
   //do something   
   callMethod();  
}  

private void callMethod(){  
   //do something  
   try {  
     Thread.sleep(5000);    
   } catch(InterruptedException e){  

   }
}

我的while循环会再次中断吗?

3 个答案:

答案 0 :(得分:1)

Thread.sleep()会在投掷InterruptedException之前清除“中断状态”。你需要在catch块中调用Thread.currentThread().interrupt(),否则while条件很可能不会成功,因为当callMethod返回时,线程将始终“不被中断”。

异常不是由interrupt()方法引起的,而是由sleep()阻塞已发出“已中断”信号的线程引起的。这将更详细地解释here。另请参阅this answer

答案 1 :(得分:1)

在线程上调用中断本身不会引发异常。在设置中断标志时休眠或等待是导致InterruptedException被抛出的原因。

可以完全预测可以抛出InterruptedException的内容,以便被中断的线程具有控制权并且可以选择如何响应。它是一个经过检查的例外,因此很明显会抛出它。它不像ThreadDeath,它可以被抛出任何地方。

当抛出InterruptedException时,线程的中断状态被重置。如果要恢复线程的中断状态,因为您想稍后检查该标志并使其成为真,请调用Thread.currentThread().interrupt()进行设置。

在更改指令处理方式的过程中,没有任何异常情况发生。因此,如果您选择在循环中捕获InterruptedException并检查标志以退出,则需要重置标志:

while(!Thread.currentThread().isInterrupted()){  
   //do something   
   try{  
     Thread.sleep(5000);    
   } catch(InterruptedException e){  
        Thread.currentThread().interrupt();
   }
}

或者,您可以使用InterruptedException退出循环:

try {
    while (!Thread.currentThread().isInterrupted()) {
        // do something
        Thread.sleep(5000);
    }
} catch (InterruptedException e) {
    // flag value is not used here, but still good style
    Thread.currentThread().interrupt(); 
}

如果最后一个片段是被中断的线程的整个运行方法,你可以在不设置中断状态的情况下再次使用,但是如果你有其他部分使用的组件你不想要一个表现不好的人部分压制中断的标志,以便线程中的其他代码不知道中断。

答案 2 :(得分:0)

实际上,您的问题更多地是关于try - catch - finally而不是多线程。

1)如果sleep抛出Exceptioncatch块将会执行,然后while循环继续。

2)你做的与1)完全相同

要离开while循环,请执行:

try{  
   while(!Thread.currentThread.isInterrupted){  
       //do something   
       Thread.sleep(5000);    
   }  
}
catch(InterruptedException e){  

}

在这种情况下,如果抛出Exception,则会保留while循环并执行catch块。