CompletableFuture 是否在重新抛出异常时完成?

Does a CompletableFuture completes on a re-thrown exception?

我刚开始使用 CompletableFuture 并且已经爱上它了。

但是在我使用 CompletableFuture 时出现的一件奇怪的事情是它的方法称为“exceptionally”

假设我有一个 CompletableFuture<?> cf1.

现在,一旦数据到达,我的代码就会应用一些处理逻辑。如果出现异常,我使用 exceptionally 方法重新抛出 MyCustomException

cf1  
.thenApply(myData->Some Processing Logic)  
.exceptionally(ex-> throw new MyCustomException())

cf.get(); 

有趣的是,对 get 方法的调用无限期挂起,直到我终止程序。这是否意味着如果 CompletableFuture 从 exceptionally 块中重新抛出异常,未来将不会被标记为完成?我需要明确地将其标记为完成吗?

根据文档,如果未来异常完成,get 方法会抛出异常

ExecutionException - if this future completed exceptionally

所以你可以 return 来自 exceptionally 的一些值来识别在 thenApply 期间抛出的异常并调用 get

的方法

第二种方法,在调用get方法之前,你可以使用allOf使未来对象完成,并检查未来是否异常完成

CompletableFuture.allOf(completableFuture);
completableFuture.isCompletedExceptionally();  //true

这是一个示例代码,它在抛出异常时没有完成 -

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);