【问题标题】:Interrupted exception vs isInterrupted in a while loop在while循环中中断异常与isInterrupted
【发布时间】:2013-02-03 21:26:34
【问题描述】:

假设我有以下代码:

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 循环会再次中断吗?

【问题讨论】:

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


【解决方案1】:

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

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

2) 你做的事情和 1) 完全一样

要离开while 循环,请执行以下操作:

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

}

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

【讨论】:

  • +1:但是我更喜欢在循环中捕获异常,然后显式中断或继续。
  • @BigMike 是的,这种方法完全符合 Java 格言“更多代码意味着更好的代码”。
  • @MarkoTopolnik 只是我不想使用 catch 块来控制我的程序流程,如果我需要从循环中退出,我想成为一个明确表示中断的人,那只是为了明天谁会继承我的代码......
  • @BigMike 换句话说,您更喜欢没有异常机制的语言。无论您喜欢与否,异常都会控制流程;您只需让他们以涉及更多代码的方式控制流程。
  • @MarkoTopolnik 也许你是对的,我想像往常一样,这取决于个人品味和场景。顺便说一句,我真的很讨厌 java,仍然爱上了好的旧 C ;)
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    在线程上调用中断本身不会引发异常。设置中断标志时休眠或等待是引发 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(); 
    }
    

    如果最后一个 sn-p 是被中断线程的整个运行方法,则无需再次设置中断状态即可过关,但如果您有组件正在被其他部分使用,则您不希望有一个表现不佳的组件部分压制中断标志,以便线程中的其他代码不知道中断。

    【讨论】:

      猜你喜欢
      • 2017-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-14
      • 2019-05-05
      • 2013-06-26
      相关资源
      最近更新 更多