为什么thenComposeAsync等待返回可以兑换

set*_*hwm 6 java java-8 completable-future

我写了一个人为的代码示例,它可能不是某人应该使用的代码,但我相信它应该有效.然而它反而陷入僵局.我已经阅读了这里描述的答案,但发现它们不足.

这是代码示例:

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

public class Test {

    public static void main(String argv[]) throws Exception {

        int nThreads = 1;
        Executor executor = Executors.newFixedThreadPool( nThreads );



        CompletableFuture.completedFuture(true)
            .thenComposeAsync((unused)->{

                System.err.println("About to enqueue task");
                CompletableFuture<Boolean> innerFuture = new CompletableFuture<>();
                executor.execute(() -> {

                    // pretend this is some really expensive computation done asynchronously

                    System.err.println("Inner task");
                    innerFuture.complete(true);
                });
                System.err.println("Task enqueued");

                return innerFuture;
            }, executor).get();

        System.err.println("All done");
        System.exit(0);

    }

}
Run Code Online (Sandbox Code Playgroud)

这打印:

即将入队任务

任务排队

然后它挂了.它已陷入僵局,因为执行程序只有一个线程,并且它正在等待innerFuture变为可兑换.为什么它的返回值"thenComposeAsync"块成为可兑换的,而不是返回仍然不完整的未来,并在执行释放它的线程?

这感觉完全不直观,javadocs并没有真正帮助.我是否从根本上误解了CompletionStages的工作原理?或者这是实施中的错误?

set*_*hwm 4

因此,经过多次有趣的对话后,我决定给一位 JDK 作者发送电子邮件。发现这种行为并非有意为之,而且确实是 1.8u25 中存在的错误。有一个修复程序将随 Java 8 的更高版本补丁一起发布。我不知道是哪个。对于任何想要测试新行为的人,您可以在此处下载最新的 jsr166 jar:

http://gee.cs.oswego.edu/dl/concurrency-interest/index.html