简单 completableFuture.exceptionally() 异常完成时未触发()

simple completableFuture.exceptionally() not triggered when completing exceptionally()

我不明白一些基本的东西。

public static void main(String[] args) {
    CompletableFuture<String> cf = new CompletableFuture<>();
    cf = cf.exceptionally(throwable ->  "inside exceptionally");

    cf.completeExceptionally(new IOException());
    String s = "im empty";
    try {
        s = cf.get();
    } catch (InterruptedException e) {
        System.out.println("inside InterruptedException catch");
    } catch (ExecutionException e) {
        System.out.println("inside ExecutionException catch");
    }
    System.out.println(s);
}

我希望这段代码输出什么=

inside exceptionally

实际输出:

inside ExecutionException catch

im empty

来自 .exceptionally javadoc:

Returns a new CompletableFuture that is completed when this CompletableFuture completes, with the result of the given function of the exception triggering this CompletableFuture's completion when it completes exceptionally; otherwise, if this CompletableFuture completes normally, then the returned CompletableFuture also completes normally with the same value.

如果是这样,为什么会触发 get 的捕获? 我假设我异常完成它会触发 .exceptionally() 方法并给我一个有效的字符串响应...

我错过了什么?

在此代码段中

CompletableFuture<String> cf = new CompletableFuture<>();
cf = cf.exceptionally(throwable ->  "inside exceptionally");

您正在创建一个 CompletableFuture,稍后打算完成并将其引用分配给 cf。然后 exceptionally 您调用 returns 一个新的 CompletableFuture 引用,您将其分配回 cf 并导致您丢失原始文件。

当你稍后打电话时

cf.completeExceptionally(new IOException());

您是在 exceptionally 返回的 CompletableFuture 上执行此操作,而不是原始文件。原文

CompletableFuture<String> cf = new CompletableFuture<>();

仍然不完整。

最后,当你打电话时

s = cf.get();

您再次对 exceptionally 返回的 CompletableFuture 执行此操作,该 CompletableFuture 使用 IOException 异常完成。你会注意到,如果你调用

e.getCause();

在该 catch 块中,它将包含 IOException


您正在链接期货,但想对它们进行操作。您想要完成原件并从 exceptionally() 返回的结果中获得结果。所以将它们都存储在自己的变量中并做你的事情。例如,

CompletableFuture<String> root = new CompletableFuture<>();
CompletableFuture<String> dependent = root.exceptionally(throwable -> "inside exceptionally");

root.completeExceptionally(new IOException());
String s = "im empty";
try {
    s = dependent.get();
} catch (InterruptedException e) {
    System.out.println("inside InterruptedException catch");
} catch (ExecutionException e) {
    System.out.println("inside ExecutionException catch");
}
System.out.println(s);

这将打印

inside exceptionally

意味着 Function 传递给 exceptionally 是在 root CompletableFuture 异常完成时执行的。