在Guava中使用Throwables.propagate(e)时,处理InterruptedException的最佳实践是什么?

我喜欢使用throw Throwables.propagate(e),尤其是在不抛出任何检查异常的方法中,并且异常处理是调用者的责任。但这并不能满足我对InterruptedException的期望。

我不想失去线程被中断的事实,所以我最终写了这样的东西:

public void run() {
    Callable c = ...;
    try {
        c.call();
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        throw Throwables.propagate(e);
    } catch (Exception e) {
        throw Throwables.propagate(e);
    }
}

Guava 有办法做到这一点吗?是否有一种(向后兼容?!)的方式来使用类似Throwables.propagate()的方法(如果该方法包装并传播了InterruptedException,则将该线程设置为中断)?

最佳答案

方便地,我们前一段时间在内部进行了讨论。我将复制并粘贴:

我对Throwables.propagate(e)的强硬意见是,它基本上是throw new RuntimeException(e),人们通常不应该这样做,就像他们通常不应该编写throw new RuntimeException(e)一样。 (而且,如果他们要编写它,那么不妨直接编写它,这样可以清楚地知道发生了什么。)

我对catch (Exception e)的强硬意见(通常是人们如何陷入困境)是他们通常也不应这样做。 (显然,在某些情况下catch (Exception e)显然是正确的做法(基本上是任何顶级的Operation-scope catch块),但这些情况是显而易见的。)

我对InterruptedException的强硬意见是,完全通过这种方式破坏InterruptedException实现Exception:这需要其他异常不需要的特殊处理。

我对将InterruptedException转换为RuntimeException的强硬看法是“不要”。 (与我上面提到的其他许多内容一样,这也引起了争议。)

因此,一方面,我不确定我们可以做些什么来挽救propagate()。另一方面,使该方法的错误程度降低一点也许是一件好事。

再考虑一下这个调用者,它捕获了ExecutionException e:
throw Throwables.propagate(e.getCause());
中断使用者线程是错误的,就像直接抛出e.getCause()一样是错误的,因为该中断是针对计算线程而不是使用者线程的。

我倾向于不让propagate()。 (您可能会猜到,我个人倾向于弃用它,但这是一个更大的讨论。)

10-06 08:34