如果没有人调用interrupt(),可以忽略InterruptedException吗?

Hil*_*kus 39 java multithreading exception-handling thread-safety interrupted-exception

如果我创建自己的线程(即不是线程池)和我调用的某个地方sleep或任何其他可中断的方法,如果我知道代码中没有其他人在线程上执行中断,则可以忽略InterruptedException .

换句话说,如果线程应该和JVM一样长,这意味着线程不可中断,是否可以安全地假设InterruptedException 永远不会被调用,因此可以吞下异常?

Zhe*_*dar 33

忽略已检查的异常从不被视为安全.
你现在可能没问题,但如果另一个程序员扩展你的代码,他会期望标准行为:线程对中断调用作出反应.
在这种情况下,空的catch块也很危险,因为JVM会删除中断的标志,并且应该再次设置它

Thread.currentThread().interrupt();
Run Code Online (Sandbox Code Playgroud)

在拦截区.在我看来,这是InterruptedExceptions 的最小捕获实现.检查isInterrupted循环中的标志也不会造成太大影响.
与您未来的程序员自己一两天的麻烦搜索意外的线程行为相比,这是一个很小的开销,因为您的项目可能会有所增长.

如果您认为代码的可读性受到这些catch实现的影响,您可以实现自己的safeSleep实用程序方法,该方法负责处理Exceptions并正确设置标记.

在另一方面,InterruptedException不是由JVM本身在硬件故障的情况下抛出,这是指示的用户Exception.因此,如果您没有传播您Thread的引用,则不会有其他任何Thread能够调用Thread.interrupt()它的引用.这是技术上的.但是你不应该低估人为因素和你的程序演变.
编辑:正如Ruakh指出的,实际上有一种方法可以获得一个Thread参考,从而安排一个Thread.interrupt()电话.这样,开发人员可能甚至不需要查看实现不间断的类Thread.在我看来,这是另一个原因,实现适当的异常处理.
另一件事:如果你没有投掷Exception,在这样的事件上记录这样的事件INFO可能是一个不错的选择.

  • 什么是"标准行为?" 清理并关闭? (2认同)
  • Re:"如果你没有传播你的`Thread的引用,就不会有任何其他`Thread`s,它能够调用`Thread.interrupt()`":线程不像随机对象,你可以决定是否传播.JDK提供了查找所有线程的方法.有几种方法,请参见http://stackoverflow.com/questions/1323408/get-a-list-of-all-threads-currently-running-in-java. (2认同)

Dan*_*etz 32

而不是吞下它,如果你确定它永远不会发生,你可以崩溃而不是忽略它.例如,抛出一个Error(或一个RuntimeException):

try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    throw new Error(e);
}
Run Code Online (Sandbox Code Playgroud)

Javadocs中出错:

Error是Throwable的子类,表示合理的应用程序不应该尝试捕获的严重问题.大多数此类错误都是异常情况.

如果你认为值得假设某些事情永远不会发生,那么如果它确实发生了,那就是一个"异常情况",谁知道,这可能只是一个"严重问题".

另一种看待这种情况的方法是,如果将来某人确实打断了你的方法,他们是否有可能希望它继续运行,好像什么也没发生过?我猜不会.

  • 我通常使用`AssertionError`,但这主要是个人偏好. (9认同)
  • 而且,之后,当它崩溃了六个月后,因为你写了一些需要打断它的东西,你会记得为什么你决定不先默默地吞下这个错误.或者,您将有一个微妙的错误,例如数据未保存到数据库,内存泄漏或此线程可能持有的任何其他资源. (2认同)
  • @Dorus问题是在线程内写的代码.你不能从[`Runnable.run()`](http://docs.oracle.com/javase/7/docs/api/java/lang/Runnable.html#run())中抛出一个`InterruptedException`除非它包裹在别的东西里面.如果你的意思是,"在你调用的某个方法中抛出`InterruptedException`",当然,但是你在调用它的线程中做了什么? (2认同)

Hol*_*ger 16

如果你认为它永远不会发生,你永远不应该吞下一个例外.可以决定不添加处理从未发生过的条件的代码,但它不应该以静默方式发生.

你应该做的最低限度是:

catch(InterruptedException ex) {
  throw new AssertionError(ex);
}
Run Code Online (Sandbox Code Playgroud)

这可以确保无论何时断言这种情况永远不会发生错误,您都会注意到.此模式也适用于其他意外异常,例如,IOException当您知道目标OutputStream是a ByteArrayOutputStreamAppendablea Formatter应该是a时StringBuilder,等等.


顺便说一句,还有一个Thread.sleep不需要处理的替代方案InterruptedException:

LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(timeInMillis));
Run Code Online (Sandbox Code Playgroud)

这种方法只会更早返回时,线程已经中断和保留的中断状态,Thread所以它已经为你的代码由别人谁的情况下,正确处理使用中断(假设你的代码检查的调用者然后中断状态).


Fiz*_*izz 9

在这些问题上我仍然认为圣经的书,Goetz等.Java Concurrency in Practice在第7章中提到了以下重要内容(Goetz的developerWorks文章中提供了相同的材料,它具有免费的优势,但本书在某些方面更为明确.)

中断是一种合作机制.一个线程不能强迫另一个线程停止正在做的事情并做其他事情; 当线程A中断线程B时,A只是请求B当它到达一个方便的停止点时停止正在做的事情 - 如果感觉就好了.

[...]

只有实现线程中断策略的代码才可以吞下中断请求.通用任务和库代码永远不应吞下中断请求.

所以,是的,你可以InterruptedException在你概述的情况下"吞下" .

这本书中的一个重点:

因为每个线程都有自己的中断策略,所以除非知道中断对该线程的意义,否则不应该中断线程.

所以,你可以选择像"崩溃"了自己的政策RuntimeException,AssertionError,只是记录它作为一个警告,或者完全忽略中断,只要你记录此问题的其他任何人可能需要知道.什么是最好的取决于你的线程在做什么,你没有提供任何细节.例如,如果它在火箭上运行[比如说做态度控制],你不想让JVM /火箭崩溃只是因为一个同事程序员[甚至可能不和你在同一家公司工作,例如他写了一些库你在他的代码中忘记了某个合同,并在你的代码中转储了一个安全可忽略的异常:"发生的异常不是由于随机故障而是设计错误."


Jan*_*Jan 7

如果你的Projekt变得越来越复杂,那就越来越难以说绝对没有人会调用中断方法.如果某人有一天会调用此方法并且发生InterruptedException,那么如果您至少没有在某处记录它,那么很难调试它.


man*_*uti 6

不应该忽视它.它应该被抛回调用者,或者你应该重新设置线程的中断状态,该状态在抛出异常时被清除:

catch (InterruptedException e) { 
     // Restore the interrupted status
     Thread.currentThread().interrupt();
 }
Run Code Online (Sandbox Code Playgroud)

除非你提示退出捕获后的线程.

是一篇关于处理s的文章InterruptedException.

  • 如果你只是重新抛出异常,那么与使用不推荐使用的Thread.stop()方法杀死线程的效果是否相同?谁会抓住这个例外? (2认同)