在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()
。 (您可能会猜到,我个人倾向于弃用它,但这是一个更大的讨论。)