我应该在`throw new InterruptedIOException()`之前执行`Thread.currentThread()。interrupt()`吗?

时间:2015-11-17 12:25:54

标签: java android multithreading

我实现MyInputStream.read()并注意到此函数中可能会发生InterruptedException。经过一些搜索,我发现抓住InterruptedException并重新抛出InterruptedIOException是很常见的,例如:

    try {
        ...
    } catch (InterruptedException e) {
        //Thread.currentThread().interrupt(); // <=== ???
        throw new InterruptedIOException();
    }

但只有约50%的代码示例执行Thread.currentThread().interrupt()。 好吧,我同意the worst thing you can do with InterruptedException is swallow it,但 我应该在抛出不同的异常之前重新中断当前的线程吗?

PRO:单个中断请求可能有多个“收件人”。

CONTRA:在中断状态被清除之前,某些功能like logging可能无法正常工作,这可能会导致细微的错误。

CONTRA:我们收到两条关于中断请求的通知:线程的中断状态和异常。最初,只有一个通知:线程的中断状态为true或抛出InterruptedException,但不是两者都有。

PRO:没有人真正针对可能引发的i / o异常测试代码,InterruptedIOException与其他i / o异常不同; catch(IOException)子句可能会吞下中断状态。

PS看起来就像我做的那样,InterruptedIOException是一种非常特殊的需要特殊处理程序的IOException的问题将无法解决。

PPS(编辑) 我不能让原始的InterruptedException传播,因为InputStream.read()不能抛出InterruptedExceptionthrows IOException而不抛出任何其他东西)。 我无法预测将调用MyInputStream.read()的上下文:MyInputStream的实例可以传递给任何带有InputStream参数的Java或第三方库函数。

关于the old bug,看起来它只是关闭,而不是固定;并且中断状态的想法是代码表现不同。

3 个答案:

答案 0 :(得分:1)

我建议投一个 ClosedByInterruptException 。虽然它属于NIO库,但它具有比旧InterruptedIOException更好的API,使其更易于处理。例如:

try {
    ...
} catch (InterruptedException e) {
    close(); // obeying API of ClosedByInterruptException
    Thread.currentThread().interrupt(); // again, obeying API
    throw new ClosedByInterruptException();
}

另见Thread#interrupt()。如果您想要重新抛出原始异常,可以使用:

try {
    ...
} catch (InterruptedException e) {
    throw e;
}

所以你保持堆栈跟踪。在这种情况下,中断状态保持畅通,因为InterruptedException的API建议。

答案 1 :(得分:1)

  

...我应该在抛出不同的异常之前重新中断当前线程吗?

如果某个upstack会检查中断标志,那么是。否则,没关系。

  

CONTRA:在中断状态被清除之前,某些功能(如日志记录)可能无法正常工作,这可能会导致细微的错误。

通过阅读分析,您链接的错误仅适用于Java 6及更早版本,仅适用于Solaris平台。你现在可以打折它。 (除非您的客户有口号,否则您不应该为Java 6或更早版本做过重要的应用。)

  

CONTRA:我们收到两条关于中断请求的通知:线程的中断状态和异常。

它们是定性不同的通知......

  

PS看起来就像我做的那样,InterruptedIOException是一种非常特殊的需要特殊处理程序的IOException的问题将无法解决。

事实上,更好的策略可能是在InterruptedIOException的catch中设置中断标志...或者只是允许原始Interrupted异常传播。

答案 2 :(得分:1)

由于以下原因:

  1. InterruptedException绝不能被吞下,

  2. 任何IOException(特别是InterruptedIOException)可以 吞下,即被第三方代码消费

  3. IOException旨在通知i / o发生的事件,而不是线程状态的变化

  4. 我们无法控制的某些代码可能会在投掷或重新投掷之前设置或清除线程中断状态InterruptedIOException

  5. 我决定:

    1. 在投放InterruptedIOException之前必须重新中断当前主题。
    2. 代码处理InterruptedIOException不应假设线程中断状态的任何特定状态
    3. 必须记录此行为:

      @throws InterruptedIOException if the current thread is interrupted (the thread
              interrupted status is true when InterruptedIOException is thrown)
      @throws IOException if this stream is closed or another IOException occurs.
      
      Note that due to possible interference from 3rd-party code, handlers 
      of InterruptedIOException should not assume any particular state
      of the thread interrupted status when they are invoked.