假设我有以下代码:
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,它与多线程无关。