【发布时间】:2017-11-09 15:27:22
【问题描述】:
我找不到方法(无论是通过 SO 还是调试我的代码)来允许从胎面抛出的异常传播到主线程。我已经尝试过使用Thread.setUncaughtExceptionHandler() 和CompletableFuture:.exceptionally(),.handle(),...
关键是通过这些机制(正如我调试的那样),实际处理是在工作线程上执行的,而不是在主线程上 - 我无法设法将它送到主线程。
总的来说,我正在编写一个测试,如果异常在工作线程中引发,它永远不会到达运行测试的主线程,即使出现问题,测试也会通过。
我需要那个异常会引发异步;我迫不及待地等待未来完成,因为我需要立即从主线程返回一个流(一个 PipedStream)而不阻塞。
我得到的唯一提示是控制台错误(只有当我使用传统的 Thread + uncaughtExceptionHandler 方法时,当我尝试使用 CompletableFuture 时根本没有日志):
Exception: com.example.exception.MyException thrown from the UncaughtExceptionHandler in thread "Thread-5"
或者如果我没有定义异常处理程序:
Exception in thread "Thread-5" com.example.MyException: Exception message
我提供一些代码:
try {
@SuppressWarnings("squid:S2095") final PipedOutputStream pos = new PipedOutputStream();
final PipedInputStream pis = new PipedInputStream(pos);
CompletableFuture.runAsync(pipeDecryptorRunnable(inputStream, pos));
return pis;
} catch (IOException e) {
throw new CryptographyException(e.getMessage(), e);
}
pipeDecryptorRunnable 内部是一个解密数据的 CipherStream。那里抛出异常。但是我无法在主线程中捕获它并且变得不可见。从该方法返回的pisstream 用于读取数据,并且工作线程在读取数据时即时解密数据pis。
编辑:
UncaughtExceptionHandler 正如类似问题中的答案所暗示的那样不适用于我的场景,因为处理程序代码是由工作线程调用的,而不是主线程。
【问题讨论】:
-
"我等不及 future 完成" => 一旦抛出异常,future 就会完成。如果您显示 minimal reproducible example 解释您期望的行为可能会有所帮助。
-
您希望这样的事情如何运作?只是在主线程中的随机执行点抛出一个随机异常?
-
描述你需求的方式,根本做不到。如果您只是触发并忘记了您的工作线程并且从不等待其完成,那么主线程很可能在工作线程到达异常抛出点之前已经完全完成。
-
您已经在工作线程和调用者(主)线程之间建立了一条通信路径,即管道。您可以使用它来传输异常:扩展 PipedInputStream(可能还有 PipedOutputStream),使 read() 方法抛出 IOException,包装工作端提供的原始异常。
-
无法发布答案,因为问题已关闭 :-(。使用仅存储异常对象的
setException(Throwable foreignException)方法扩展 PipedInputStream。覆盖各种read()方法以抛出 @ 987654338@ 如果存在。使PipedInputStream pis可用于您的工作线程,以便您可以在catch 子句中调用pis.setException()。访问PipedInputStream 的一种方法可能是还使用setException()方法扩展PipedOutputStream与消费者PipedInputStream通信。
标签: java multithreading stream completable-future