为什么此代码的结果不确定?

问题描述

我希望以下代码始终打印“错误”,但有时却打印“外部”。我要发生的是使“外部”完成,使“内部”使用“外部”的结果生成自己的结果,如果任何将来失败,都会失败。我在做什么错了?

        CompletableFuture<String> outer = CompletableFuture.supplyAsync(() -> "outer");
        CompletableFuture<String> inner = CompletableFuture.supplyAsync(() -> "inner");
        inner.completeExceptionally(new IllegalArgumentException());
        CompletableFuture<String> both = outer.thenApply(s -> {
            try {
                String i = inner.get();
                return s + i;
            } catch (InterruptedException |ExecutionException e) {
                throw new IllegalStateException(e);
            }
        });

        try {
            String o = both.get();
            System.out.println(o);
        } catch (ExecutionException | InterruptedException e) {
            System.err.println("Errored");
        }

解决方法

了解这一点实际上很简单。您需要对此进行更仔细的研究:

CompletableFuture<String> inner = CompletableFuture.supplyAsync(() -> "inner");

具体来说,您说的是supplyAsync,这意味着在另一个线程中。在主线程(或其他任何线程)中,您可以执行inner.completeExceptionally(new IllegalArgumentException());

哪个线程应该赢?来自supplyAsync的一个还是您运行inner.completeExceptionally的一个?当然,completeExceptionally的文档中提到了这一点……这是一个基本的“竞赛”,首先到达inner的那个线程到达“完成”(正常或通过异常)。

,

了解发生了什么的关键是在completeExceptionally的{​​{3}}中。

如果尚未完成,则导致get()和相关方法的调用引发给定异常。

在您的示例中,您正在创建两个期货,这些期货将异步完成,然后您调用completeExceptionally来告诉其中一个期货引发异常而不是传递结果。

根据您的发言,看来inner的将来有时在您致电completeExceptionally时已经完成了。在这种情况下,completeExceptionally调用将不会有任何影响(按照规范),随后的inner.get()将传递(已经)计算出的结果。

这是比赛条件。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...