我一直在玩CompletableFuture
,发现一个奇怪的东西。
String url = "http://google.com";
CompletableFuture<String> contentsCF = readPageCF(url);
CompletableFuture<List<String>> linksCF = contentsCF.thenApply(_4_CompletableFutures::getLinks);
linksCF.thenAccept(list -> {
assertThat(list, not(empty()));
});
linksCF.get();
如果在我的 thenAccept
调用中,断言失败,则不会传播异常。
然后我尝试了一些更丑陋的东西:
linksCF.thenAccept(list -> {
String a = null;
System.out.println(a.toString());
});
什么都没有发生,也没有传播异常。我尝试使用 handle
和其他与 CompletableFutures
中的异常相关的方法,但失败了 - 没有一个按预期传播异常。
当我调试 CompletableFuture
时,它确实会捕获如下异常:
final void internalComplete(T v, Throwable ex) {
if (result == null)
UNSAFE.compareAndSwapObject
(this, RESULT, null,
(ex == null) ? (v == null) ? NIL : v :
new AltResult((ex instanceof CompletionException) ? ex :
new CompletionException(ex)));
postComplete(); // help out even if not triggered
}
没有别的了。
我使用的是 JDK 1.8.0_05 x64,Windows 7。
我错过了什么吗?
最佳答案
问题是您从不请求接收对 linksCF.thenAccept(..)
的调用结果。
您对 linksCF.get()
的调用将等待您的链中的执行结果。但它只会返回 then linksCF future 的结果。这不包括您的断言结果。
linksCF.thenAccept(..)
将返回一个新的 CompletableFuture 实例。要获取抛出的异常调用 get()
或在新返回的 CompletableFuture 实例上使用 isCompletedExceptionally()
检查异常状态。
CompletableFuture<Void> acceptedCF = linksCF.thenAccept(list -> {
assertThat(list, not(empty()));
});
acceptedCF.exceptionally(th -> {
// will be executed when there is an exception.
System.out.println(th);
return null;
});
acceptedCF.get(); // will throw ExecutionException once results are available
替代方案?
CompletableFuture<List<String>> appliedCF = linksCF.thenApply(list -> {
assertThat(list, not(empty()));
return list;
});
appliedCF.exceptionally(th -> {
// will be executed when there is an exception.
System.out.println(th);
return Coolections.emptyList();
});
appliedCF.get(); // will throw ExecutionException once results are available
关于java - CompletableFuture 吞下异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24183246/