首页 > 解决方案 > Completablefuture 在异常时未完成

问题描述

我对使用 CompletableFuture API 有点陌生,我对allOf. 根据我的阅读,completable-future 应该处于完整状态,并且allOf应该在所有关联的期货完成时执行逻辑,包括completed-exceptionally. 但这是我的代码allOf块永远不会被执行 -

public static void test() {
    CompletableFuture<String> r1 = CompletableFuture.supplyAsync(() -> {
        try{
            Thread.sleep(1000);
            throw new RuntimeException("blahh !!!");
        }catch (Exception e) {
            throw new RuntimeException(e);
        }
    });

    CompletableFuture<String> r2 = CompletableFuture.supplyAsync(() -> "55");
    CompletableFuture<String> r3 = CompletableFuture.supplyAsync(() -> "56");
    CompletableFuture.allOf(r1, r2, r3).thenRun(() -> { System.out.println(Thread.currentThread()+" --- End."); });
    Stream.of(r1, r2, r3).forEach(System.out::println);


    try{
        System.out.println(Thread.currentThread()+" --- SLEEPING !!!");
        Thread.sleep(3000);
        System.out.println(Thread.currentThread()+" --- DONE !!!");
    } catch (Exception e) {
        //e.printStackTrace();
    }
    Stream.of(r1, r2, r3).forEach(System.out::println);
}

标签: javacompletable-futureconcurrent.futures

解决方案


问题不在于你allOf CompletableFuture永远不会完成。确实如此。

导致您的代码无法运行的原因是thenRun的期望:

返回一个新的 CompletionStage,当此阶段正常完成时,执行给定的操作。有关异常完成的规则​​,请参阅 CompletionStage 文档。

您可能已经知道,当allOf's 的一个期货异常完成时,产生的未来也会异常完成:

当所有给定的 CompletableFuture 完成时,返回一个新的 CompletableFuture。如果任何给定的 CompletableFuture 异常完成,则返回的 CompletableFuture 也会这样做,并且 CompletionException 将此异常作为其原因。

简而言之,thenRun如果你想对你的allOf未来运行一个动作,不管它如何完成,都不要使用。作为替代方案,您可以使用whenComplete

CompletableFuture.allOf(r1, r2, r3)
        .whenComplete((a, ex) -> System.out.println(Thread.currentThread() + " --- End."));

您还可以使用thenRun+的组合exceptionally,其中一个将运行:

CompletableFuture<Void> all = CompletableFuture.allOf(r1, r2, r3);
all.thenRun(() -> {
    System.out.println(Thread.currentThread() + " --- End.");
});
all.exceptionally(ex -> {
    System.out.println(ex);
    return null;
});

推荐阅读