在 Spring Boot 应用程序中使用 CompletableFuture 时,我注意到使用 CompletableFuture 异步运行的函数中出现异常,但没有任何日志。函数执行停止,因此 CompletableFuture 完成。为什么日志里什么都没有? 当我将 .whenComplete 与 .runAsync 一起使用时,我能够记录错误。
void function() {
CompletableFuture
.runAsync(() -> runAsyncfunction())
.whenComplete((result, err) -> {//log the error})
}
编辑:如果我不使用.whenComplete
JVM 不会打印 runAsyncfunction
中发生的未捕获异常的堆栈跟踪自动地。但如果我使用 .whenComplete
我可以记录异常。
此外,使用 .whenComplete
是否是良好的行业实践?在这种情况下?
最佳答案
“JVM”不会自行打印异常堆栈跟踪。您需要编写代码来实现它。我能想到的唯一可能发生的情况是异常从 main() 中逃逸。否则,您编写的代码或您调用的代码具有打印堆栈跟踪的明确指令。也许如果您的代码是从某些 Spring Boot 代码调用的,Spring Boot 代码有一个异常处理程序可以为您执行此操作 - 我不知道,我不使用它。
在这种情况下
someFuture.runAsync(() -> runAsyncfunction());
当您调用 someFuture.runAsync() 时,您将返回一个新的 CompletableFuture,但您已忽略它。
当 someFuture 完成时,您的 runAsyncFunction() 将执行,可能在其他线程中。如果抛出异常,“您忽略的 future ”将异常完成。但你永远不会发现它,因为你忽略了会告诉你的机制。
总结一下:在其他线程(运行异步例程的线程)中引发了一些异常。那个异常在那里被捕获,并用来“异常地完成 future ”。但你需要做点什么才能发现 future 已经完成;在您这样做之前,它只是 future 未经检查的状态信息。
这个结构:
someFuture.runAsync(() -> runAsyncfunction())
.whenComplete(blah blah);
相当于
CompletableFuture<Void> x =
someFuture.runAsync(() -> runAsyncfunction());
x.whenComplete(blah blah);
也许这能让我们更清楚地了解这种情况下发生的事情。 “runAsync”失败,“x”异常完成。然后,whenComplete 会触发,您可以针对失败执行一些有用的操作。
脚注:发布的代码对我来说看起来无效。
CompletableFuture
.runAsync(() -> runAsyncfunction())
.whenComplete((result, err) -> {//log the error})
所以我希望我正确地猜出了你的意图。
关于java - 为什么 completablefuture 不记录异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69839401/