如何控制CompletableFuture的流程?

时间:2018-01-27 08:55:31

标签: java completable-future

请考虑以下代码:

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

我注意到以下行为:

  • 未来正常完成时,仅打印EXCEPTION 1。这是预期的,因为我们在thenAcceptAsync

  • 中抛出异常
  • 如果未来异常完成,则会同时打印EXCEPTION 1EXCEPTION 2

我只想在执行EXCEPTION 1时发生异常时打印thenAcceptAsync。所以在第二种情况下,当异常完成未来时,我只想打印EXCEPTION 2

如何使用CompletableFuture执行此操作?我知道我可以在try / catch中添加一个好的旧thenAcceptAsync,但我想知道是否可以仅使用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流程,我们会返回null。现在使用thenAcceptAsync参数调用null。我们可以对参数null添加o检查,但我认为这不是一个好主意。我们正在唤醒执行程序线程,发现参数onull

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

1 个答案:

答案 0 :(得分:1)

怎么样:

    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.thenAcceptAsync,另一个是future.exceptionally,它们彼此分开执行。