简体   繁体   English

为什么这段代码的结果是不确定的?

[英]Why is the result of this code non-deterministic?

I would expect the following code to always print "Errored", but sometimes it prints "outerinner".我希望下面的代码总是打印“Errored”,但有时它会打印“outerinner”。 What I want to happen is for "outer" to complete and for "inner" to use "outer"'s result to generate its own result, failing if either future fails.我想要发生的是“外部”完成和“内部”使用“外部”的结果来生成自己的结果,如果未来失败则失败。 What am I doing wrong?我究竟做错了什么?

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

It's actually fairly trivial to understand this one.理解这一点实际上是相当微不足道的。 You need to look more closely at this:你需要更仔细地看看这个:

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

specifically the fact that you are saying supplyAsync , which means in a different thread .特别是您说的是supplyAsync ,这意味着在不同的线程中 While in your main thread (or any other) you do : inner.completeExceptionally(new IllegalArgumentException());在您的主线程(或任何其他线程)中,您执行以下操作: inner.completeExceptionally(new IllegalArgumentException()); . .

Which thread is supposed to win?哪个线程应该获胜? The one from supplyAsync or the one where you run inner.completeExceptionally ?来自supplyAsync还是你运行inner.completeExceptionally Of course, the documentation of completeExceptionally mentions this... It's a basic "race", which thread reaches to "complete" (either normally or via an Exception) that inner first.当然,的文档completeExceptionally提到了这一点......这是一个基本的“种族”,哪个线程达到“完全”(正常或通过一个例外),其inner第一。

The key to understanding what is going on is in the javadoc for completeExceptionally .理解发生了什么的关键是在completeExceptionallyjavadoc中。

If not already completed , causes invocations of get() and related methods to throw the given exception.如果尚未完成,则导致调用get()和相关方法抛出给定的异常。

In your example, you are creating two futures which will be completed asynchronously, then you are calling completeExceptionally to tell one of the futures to throw an exception rather than delivering a result.在您的示例中,您正在创建两个将异步完成的期货,然后您调用completeExceptionally以告诉其中一个期货抛出异常而不是提供结果。

Based on what you are saying, it appears that sometimes the inner future has already completed by the time you call completeExceptionally .根据您所说的,有时在您调用completeExceptionally时, inner未来似乎已经completeExceptionally In that case, the completeExceptionally call will have no affect (as per the spec), and the subsequent inner.get() will deliver the result that was (already) computed.在这种情况下, completeExceptionally调用将没有影响(根据规范),随后的inner.get()将提供(已经)计算的结果。

It is a race condition.这是一个竞争条件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么最大递归深度我可以达到非确定性? - Why is the max recursion depth I can reach non-deterministic? 卡尺基准测试中的非确定性分配行为 - non-deterministic allocation behavior in caliper benchmark Java 多线程的非确定性行为 - Non-deterministic behavior with Java Multithreading 具有驻留持续时间的有限可能非确定性状态机 - A finite possibly non-deterministic state machine with dwell durations JAVA Md5返回不确定的结果 - JAVA Md5 returning non-deterministic results java命令行上的非确定性进度条 - Non-deterministic progress bar on java command line 使用getHardwareAddress非确定性获取Java中的mac地址 - Get mac address in Java using getHardwareAddress non-deterministic 从科学计数法到十进制的非确定性转换 - Non-deterministic conversion from scientific notation to decimal 奇怪的Java Hashcode(带有Lombok)不确定性行为 - Odd Java Hashcode (with Lombok) Non-Deterministic Behavior Maven Surefire并行测试中跳过测试的非确定性行为 - Non-deterministic behavior of skipped tests in parallel testing on Maven Surefire
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM