【问题标题】:Best way to handle InterruptedException处理 InterruptedException 的最佳方法
【发布时间】:2016-03-01 12:34:26
【问题描述】:

我正在使用 Thread.sleep(10000);因此我需要处理 InterruptedException。我可以调用 Thread.currentThread.interrupt() 然后将异常抛出到调用类,或者我可以直接将它抛出到调用类或者有没有更好的方法来处理它?

【问题讨论】:

  • 您确定需要Thread.sleep 吗? 99% 的时间你不需要它也不应该使用它。
  • 我正在从文件中轮询消息,每次迭代前我必须等待 10 秒,所以我使用 sleep()。你能推荐我更好的方法吗
  • 信息是如何写入文件的?你能控制它吗?
  • 不,我只连接到文件路径来获取数据。
  • 使用TimerScheduledExecutorService 可能比让线程休眠

标签: java multithreading interrupted-exception interruption


【解决方案1】:

如果你有一个循环和轮询的专用线程,在我看来,这听起来像是程序结束时需要终止的东西;除非它是一个守护线程(这意味着你很高兴它消失而没有机会清理或关闭资源)它需要能够处理中断。使用 WatchService 似乎是个好主意,但是使用 WatchService 的代码仍然需要知道如何处理中断。

如果您正在编写一个休眠的 Runnable 或 Callable,您可以使用 InterruptedException 退出您正在执行的任何循环,或者您可以捕获异常并恢复中断标志,以便下一次检查中断标志(使用Thread.currentThread().isInterrupted()) 可以看到线程被中断了:

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
    Thread.currentThread().interrupt(); 
}

如果您正在开发一个希望嵌套在其他对象中的对象,则抛出异常并将其添加到方法签名中。例如,查看 java.util.concurrent 包中类的 API 文档,例如 BlockingQueue,查看 put 和 offer 等方法如何抛出 InterruptedException。当为并发创建的对象组合在一起时,它们需要合作(并确保它们不会丢失对中断状态的跟踪),以确保它们可以以响应方式清理和终止。

【讨论】:

  • while (true) 不是更清楚吗?
  • @Esteve:在第一个示例中,异常在循环内被捕获,因此它必须检查中断标志才能离开 while 循环。在替代示例中,它并不重要。但是如果在进入循环之前已经设置了标志,我宁愿立即检查标志,而不是进入睡眠方法。
  • @NathanHughes 菜鸟问题:为什么还要使用if(!Thread.currentThread().isInterrupted())?如果从 catch 块中重新抛出异常,它无论如何都会冒泡给调用者?
  • @Govinda:我认为问题假设代码位于实现 Runnable 的类的 run 方法中。不仅不能让run方法抛出已检查异常,也不能从一个线程向另一个线程抛出异常,最好在这里处理。其他地方的代码当然有可能抛出这个,通常正确的做法是在方法上放置“抛出 InterruptedException”并让它冒泡。
  • @Govinda:希望这很清楚。我想到你的问题重新阅读,也许我应该为这个答案添加更多解释
【解决方案2】:

在大多数普通代码中,您不应该使用sleep。通常有更好的方法来做你想做的事。

我可以调用Thread.currentThread.interrupt()

如果您想正常继续,但无需等待,这很有用。

然后抛出异常给调用类

或者我会抛出一个异常,你可以用你的选择来包装异常。

或者我可以直接把它扔给调用类

在这种情况下你最好不要抓住。

或者有没有更好的处理方法?

这取决于您期望线程被中断的原因。如果我不希望有中断,我会用 AssertionError 包装它

【讨论】:

    【解决方案3】:

    一般情况下,可以重投,如果不能重投,则设置中断标志。

    关于这方面的一篇好文章是http://www.ibm.com/developerworks/library/j-jtp05236/

    最相关的摘录是:

    当一个阻塞方法检测到中断并抛出 InterruptedException,它清除中断状态。如果你抓住 InterruptedException 但不能重新抛出它,您应该保留 证明中断发生的证据,以便代码更高 调用堆栈可以了解中断并在需要时对其进行响应 到。

    【讨论】:

      【解决方案4】:

      我正在使用 Thread.sleep(10000);因此我需要处理 InterruptedException。

      不一定。处理InterruptedException 有聪明的方法,也有愚蠢的方法。如果您的线程实际上永远不会中断,那么您选择哪种方式真的很重要吗?

      当然,如果您认为您的代码可能会被重复使用,或者如果您认为其他程序员会阅读它,那么您可能希望采用聪明的方式。如果您想养成良好的编码习惯,您可能想采用聪明的方式(那里有很多示例,只是等待通过 google 搜索找到)。

      但有时我们只是想写一个快速的 hack,我们将使用一次然后扔掉......

      【讨论】:

        猜你喜欢
        • 2019-03-08
        • 1970-01-01
        • 1970-01-01
        • 2021-02-02
        • 1970-01-01
        • 1970-01-01
        • 2020-09-12
        • 2019-08-06
        • 2013-09-02
        相关资源
        最近更新 更多