【问题标题】:Java: Handling exceptions in child threadsJava:处理子线程中的异常
【发布时间】:2011-02-07 13:49:02
【问题描述】:

我更喜欢将异常处理逻辑放在调用堆栈中更靠前的位置,靠近 main 方法。我喜欢这种方法...但是,我创建了一个线程,其中 run() 中的一些方法调用可能会引发异常。我真的很想看看是否有办法将这些异常抛出回父线程?我能想到的最好的方法是在实现Runnable 的对象内设置一个变量。该变量是一个包含错误消息的字符串,然后它使用类加载器在父线程中正确地重新创建相同的异常。

我想知道的是,这里有没有一种不那么混乱的方式来获得我想要的东西? (能够确保在子线程中抛出的任何异常都使用相同的异常处理逻辑进行处理,就好像它在主线程中运行/代码重用一样)。

【问题讨论】:

  • 似乎这个问题在这里被问了很多......我会考虑关闭它但是在阅读了其他一些之后这个问题确实提出了一些不同的问题:正在使用类加载器+保存异常在可运行对象中可行吗?
  • 显然它不像 Bill K 所说的那样。谢谢。

标签: java multithreading exception-handling


【解决方案1】:

您可以在此处使用 ExecutorService 来提交可调用对象并接收 Future。此时,您至少希望将异常传播到您将调用 future.get() 的调用线程

future.get() 会将调用方法中抛出的任何异常传播到调用future.get() 的线程。因此,如果您的主线程调用 future.get(),那么主线程将看到抛出的任何异常。

【讨论】:

  • Futures 是 Java 中使用率最低的特性之一。使用 Futures 可以更安全、更轻松、更便宜地完成我需要的一半以上的直接线程使用。
  • @James 你 100% 正确,即使是简单的同步障碍,使用 Futures 也比广为人知的 CountdownLatch 和 CyclicBarrier 容易得多
  • @JohnVint - 不错的提示。一个问题 - 即使在子线程死亡(抛出 runtimeException 之后)调用 future.get() 也会抛出异常
  • @AndyDufresne 是的。 Future 本身缓冲从现在死线程传播的异常。当您调用get 时,它将检查缓冲的异常是否为非空,如果不是则将其抛出(这至少适用于当前的实现,文档不一定会这样说,但我会想象它会保持不变)。
【解决方案2】:

在 run() 方法的外层捕获它,然后将异常放在 Runnable 中的变量中,并让 Runnable 指示它已完成。

启动 runnable 的代码必须检查 Runnable 以查看“异常”对象是否已设置并重新抛出或处理它。

如果你重新抛出它,你可能想把它包装在一个新的异常中:

throw new Exception(oldException);

这将为您提供两个堆栈跟踪。

(感谢泰勒 L)

【讨论】:

  • 我认为 fillInStackTrace 会替换当前堆栈帧而不是异常的原始堆栈帧。我不确定那是你想要的。也许最好用一个新的异常来包装异常,比如 throw new YourException(originalException)。其余的似乎都很好。
【解决方案3】:

使用Thread.setUncaughtExceptionHandler(),您可以在Thread 中设置Thread.UncaughtExceptionHandler,并拥有处理线程异常的集中逻辑。

此外,您还可以编写自己的ThreadFactory,它将使用预设Thread.UncaughtExceptionHandler 创建线程。

【讨论】:

  • 我认为我唯一的问题是 Thread.UncaughtExceptionHandler 迫使我在那里处理异常,但我想把它扔回 main() 的几个堆栈。
猜你喜欢
  • 2011-10-15
  • 1970-01-01
  • 1970-01-01
  • 2013-09-10
  • 2013-10-06
  • 2014-03-23
  • 2011-04-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多