【问题标题】:Guava: Throwables.propagate and InterruptedException番石榴:Throwables.propagate 和 InterruptedException
【发布时间】:2012-10-10 12:09:07
【问题描述】:

在 Guava 中使用 Throwables.propagate(e) 时处理 InterruptedExceptions 的最佳做法是什么?

我喜欢使用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?

【问题讨论】:

  • 我会将此作为 Guava 中的功能请求提出

标签: java exception-handling guava interrupted-exception


【解决方案1】:

很方便,我们不久前在内部讨论过这个问题。我只是复制和粘贴:

我对@9​​87654321@ 的强硬意见是它基本上是throw new RuntimeException(e),人们通常不应该这样做,就像他们通常不应该写throw new RuntimeException(e) 一样。 (而且如果他们要写,他们还不如直接写出来,以便清楚发生了什么。)

我对@9​​87654324@(通常是人们如何让自己陷入这种混乱)的强硬意见是,他们通常也不应该这样做。 (显然在某些情况下catch (Exception e) 显然是正确的做法(基本上是任何顶级的操作范围的 catch 块),但这些都是......显而易见的。)

我对@9​​87654326@ 的强硬意见是,让InterruptedException 实现Exception 完全是这样被破坏的:它需要特殊处理,而其他异常则不需要。

我对将InterruptedException 转换为RuntimeException 的强硬意见是“不要”。 (就像我上面所说的许多其他内容一样,这也是有争议的。)

所以一方面,我不确定我们能做些什么来挽救propagate()。另一方面,也许让方法不那么糟糕是件好事。

然后,再考虑一下这个调用者,它捕获了ExecutionException e:

throw Throwables.propagate(e.getCause());

中断消费者线程是错误的,就像直接抛出e.getCause()是错误的一样,因为中断是针对计算线程而不是消费者线程的。

我倾向于单独离开propagate()。 (您可能已经猜到了,我个人倾向于弃用它,但这是一个更大的讨论。)

【讨论】:

  • +1 有趣的点。我很惊讶人们写throw Throwables.propagate(e.getCause());!堆栈跟踪看起来就像所有事情都发生在一个线程中!
  • 谢谢,有趣的点。 +1 到 InterruptedException 实现异常是错误的,但 Java 就是它所在的位置。我认为将 InterruptedException 转换为 RuntimeException 有时是必不可少的:如果我的方法签名由外部接口修复(所以我不能抛出 InterruptedException),并且我的操作被中断(所以我不能履行我的合同),我必须抛出一个例外。除了将线程设置为中断并抛出 RuntimeException 之外,还有什么其他明智的选择?
  • 对于写throw new RuntimeException(e) ,有一个异常包装异常是令人讨厌的噪音(特别是当它没有添加任何有用的东西时,例如关于当前上下文的附加消息)。只要可以避免这种噪音(例如,它已经是未经检查的异常),那就太好了。有一种观点认为 API 应该尽可能使用未经检查的异常。即使人们不认同这个论点,仍然必须实现其他人以这种方式编写的接口。所以请不要弃用Throwables.propagate(e)!
  • 我认为throw Throwables.propagate(e); 在处理抛出您不想专门处理的已检查异常的 API 时,比将异常添加到方法签名中要好得多。我认为这是一种很好的惯用方式,可以说“这里没有具体内容,将其视为正常的执行问题”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-13
相关资源
最近更新 更多