thenApply()是否仅依赖firstMethod?CompletableFuture相关疑问
问题与代码分析
示例代码
public class Test { public static CompletableFuture<Integer> firstMethod(int x) { // Assume this method completes in 8sec. return CompletableFuture.supplyAsync(() -> { try { Thread.sleep(8000); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println("In first method"); return x + 10; }); } public static CompletableFuture<Integer> secondMethod(int y) { System.out.println("This line will be printed only when firstMethod get completed?"); return CompletableFuture.supplyAsync(() -> { System.out.println("In second method"); return y + 10; }); } public static void main(String[] args) throws ExecutionException, InterruptedException { firstMethod(5) .thenApply(fromfirst -> secondMethod(fromfirst)) .thenAccept(x -> System.out.println(x)); } }
问题
- 是否必须等
firstMethod执行完成后,thenApply()方法才会运行? thenApply()内部的所有代码是否都要等firstMethod执行完毕后才有机会运行,表现得像A完成后B才运行的同步逻辑?- 如果是这样,为何
thenApply()会在单独线程中运行?
我的假设:我原本认为thenApply()无需等待前置方法完成即可运行,但疑惑当thenApply()中的secondMethod需要依赖firstMethod的输出作为输入时,该如何处理?
解答
关于thenApply的执行时机
thenApply必须等待前置CompletableFuture(即firstMethod返回的实例)执行完成后才会触发。原因很直接:thenApply的参数fromfirst是前置Future的执行结果,没有这个结果,你根本无法调用secondMethod(fromfirst)——总不能用一个还没产生的值作为方法输入吧?
所以你代码里的secondMethod(fromfirst)这行逻辑,包括secondMethod里的打印语句,都要等firstMethod睡够8秒、返回结果后才会执行,这部分确实是依赖前置结果的顺序触发逻辑,和“A完成后再执行B”的同步逻辑效果一致。
为什么thenApply会在单独线程运行?
这是CompletableFuture的线程调度策略决定的:
- 当
firstMethod的线程完成任务后,会把thenApply的回调任务提交到默认的ForkJoinPool.commonPool()线程池,由池中的空闲线程来执行回调。 - 这么做是为了避免阻塞
firstMethod的工作线程——让执行firstMethod的线程能尽快回到线程池,去处理其他任务,提升整体的并发效率。如果让firstMethod的线程直接执行thenApply的逻辑,相当于占用这个线程做额外的工作,会降低线程池的利用率。
关于你的假设误区
thenApply的设计初衷就是处理依赖前置结果的后续逻辑,它本身就绑定了“前置完成后再执行”的规则。如果你的逻辑不需要依赖前置结果,那可以直接并行启动多个Future;但如果需要用前置结果作为输入,thenApply就是最适合的选择——它会自动帮你等待前置任务完成,再执行后续逻辑,不需要你手动写等待代码。
内容的提问来源于stack exchange,提问作者man123
相关产品推荐
相关产品推荐

