假设我有以下代码:
CompletableFuture<Integer> future
= CompletableFuture.supplyAsync( () -> 0);
thenApply 案件:
future.thenApply( x -> x + 1 )
.thenApply( x -> x + 1 )
.thenAccept( x -> System.out.println(x));
这里的输出将是2.现在是的情况 thenApplyAsync:
future.thenApplyAsync( x -> x + 1 ) // first step
.thenApplyAsync( x -> x + 1 ) // second step
.thenAccept( x -> System.out.println(x)); // third step
我读到了这个 博客 每一个 thenApplyAsync 在一个单独的线程和'同时'执行(这意味着跟随 thenApplyAsyncs 在之前开始 thenApplyAsyncs 完成),如果是这样,如果第一步未完成,第二步的输入参数值是多少?
如果不是第二步,第一步的结果会在哪里?
第三步将采取哪一步的结果?
如果第二步必须等待第一步的结果那么重点是什么 Async?
这里x - > x + 1只是为了表明这一点,我想知道的是在非常长的计算情况下。
与...有所不同 Executor 负责运行代码。每个运营商都在 CompletableFuture 通常有3个版本。
thenApply(fn) - 跑 fn 在由...定义的线程上 CompleteableFuture 它被称为,所以你通常不知道这将被执行。如果结果已经可用,它可能会立即执行。
thenApplyAsync(fn) - 跑 fn 在环境定义的执行程序上,无论情况如何。对于 CompletableFuture 这通常是 ForkJoinPool.commonPool()。
thenApplyAsync(fn,exec) - 跑 fn 上 exec。
最后结果是相同的,但调度行为取决于方法的选择。
这就是文档所说的内容 CompletableFuture's thenApplyAsync:
返回一个新的CompletionStage,当此阶段完成时
通常,使用此阶段的默认异步执行
执行工具,以此阶段的结果作为参数
提供的功能。
所以, thenApplyAsync 必须等待前一个 thenApplyAsync's 结果:
在您的情况下,您首先执行同步工作,然后执行异步工作。因此,第二个是异步的并不重要,因为它只在同步工作完成后启动。
我们把它换掉吧。在某些情况下,将首先打印“异步结果:2”,在某些情况下,将首先打印“同步结果:2”。这里有所不同,因为调用1和2都可以异步运行,在一个单独的线程上调用1,在另一个线程上调用2,这可能是主线程。
CompletableFuture<Integer> future
= CompletableFuture.supplyAsync(() -> 0);
future.thenApplyAsync(x -> x + 1) // call 1
.thenApplyAsync(x -> x + 1)
.thenAccept(x -> System.out.println("async result: " + x));
future.thenApply(x -> x + 1) // call 2
.thenApply(x -> x + 1)
.thenAccept(x -> System.out.println("sync result:" + x));
我必须指出这些名字 thenApply 和 thenApplyAsync 是绝对可怕和令人困惑的。什么都没有 thenApplyAsync 这比异步更多 thenApply 从这些方法的合同。
差异与运行函数的线程有关。提供的功能 thenApply 可以在任何线程上运行 那
- 呼叫
complete
- 呼叫
thenApply 在同一个实例上
而 thenApplyAsync 要么使用默认值 Executor (又名。线程池)或提供的 Executor。
这些函数的异步部分与异步操作最终调用的事实有关 complete 要么 completeExceptionally。这个想法来自Javascript,它与多线程无关。