如何控制 CompletableFuture 的流程?

How to control the flow of a CompletableFuture?

考虑以下代码:

final CompletableFuture<Object> future = giveMeFuture();

future.thenAcceptAsync(o -> {
    throw new RuntimeException("Some random exception happened.");
}).exceptionally(throwable -> {
    System.out.println("EXCEPTION 1: " + throwable.getLocalizedMessage());
    return null;
});
future.exceptionally(throwable -> {
    System.out.println("EXCEPTION 2: " + throwable.getLocalizedMessage());
    return null;
});

我注意到以下行为:

我只想在执行thenAcceptAsync时出现异常时打印EXCEPTION 1。所以第二种情况,future异常完成的时候,我只想打印EXCEPTION 2

如何使用 CompletableFuture 执行此操作?我知道我可以在 thenAcceptAsync 中添加一个很好的旧 try / catch,但我想知道这是否可以仅使用 CompletableFuture 功能来完成。

更新

以下流程将不起作用:

future
    .exceptionally(throwable -> {
        System.out.println("EXCEPTION 2: " +throwable.getLocalizedMessage());
        return null;
    })
    .thenAcceptAsync(o -> {
        throw new RuntimeException("Some random exception happened.");
    })
    .exceptionally(throwable -> {
        System.out.println("EXCEPTION 1: " + throwable.getLocalizedMessage());
        return null;
    });

如果我们进入 EXCEPTION 2 流程,我们 return null。现在使用 null 参数调用 thenAcceptAsync。我们可以在参数 o 上添加 null 检查,但我认为这不是一个好主意。我们在唤醒执行线程发现参数onull:

    .thenAcceptAsync(o -> {
        if (o != null) {
            // do something with the parameter
            throw new RuntimeException("Some random exception happened.");
        }
    })

怎么样:

    future
        .handleAsync((object, throwable) -> {
            if (throwable !=null) {
                    System.out.println("EXCEPTION from future completion: " + throwable.getClass().getName());
                return null;
            }
            else {
                throw new IllegalStateException("async processing failed");
            }
        })
        .exceptionally(throwable -> {
                System.out.println("EXCEPTION from completion stage: " + throwable.getClass().getName());
            return null;
        });

或将您的代码更改为:

    future
        .exceptionally(throwable -> {
            System.out.println("EXCEPTION 2: " +throwable.getLocalizedMessage());
            return null;
        })
        .thenAcceptAsync(o -> {
            throw new RuntimeException("Some random exception happened.");
        })
        .exceptionally(throwable -> {
            System.out.println("EXCEPTION 1: " + throwable.getLocalizedMessage());
            return null;
        });

每次将操作链接到 future 时,它​​都会与其他操作分开执行 "chaining"。您正在制作两个操作链,一个使用 future.thenAcceptAsync,另一个使用 future.exceptionally,并且它们彼此分开执行。