为supplyAsync与thenApplyAsync指定不同执行器,thenApply优先级如何?
CompletableFuture执行器选择:supplyAsync(E1) + thenApply/thenApplyAsync(E2)
直接说核心结论和具体行为:
- thenApply(不带执行器):完全不会用到E2,要么在supplyAsync的E1线程里执行(如果supplyAsync还未完成),要么在调用thenApply的当前线程执行(如果supplyAsync已经结束)。
- thenApplyAsync(指定E2):不管supplyAsync处于什么状态,都会把回调任务提交给E2执行,全程不使用E1。
分场景拆解
当supplyAsync还在E1线程中运行时:
- 调用
thenApply:回调逻辑会顺着E1的线程直接执行,相当于同一个任务链的延续,不需要额外线程调度。 - 调用
thenApplyAsync(E2):回调会被放到E2的线程池里,和E1的线程独立调度执行。
- 调用
当supplyAsync已经在E1中执行完成时:
- 调用
thenApply:回调直接在你调用thenApply的那个线程里跑,和E1、E2都无关。 - 调用
thenApplyAsync(E2):仍然会把回调交给E2执行,不会使用当前线程。
- 调用
代码验证示例
// 定义两个自定义执行器 ExecutorService E1 = Executors.newSingleThreadExecutor(r -> new Thread(r, "E1-线程")); ExecutorService E2 = Executors.newSingleThreadExecutor(r -> new Thread(r, "E2-线程")); // 用E1执行异步任务 CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { System.out.println("supplyAsync 运行线程: " + Thread.currentThread().getName()); return "Hello"; }, E1); // thenApply的执行线程 future.thenApply(s -> { System.out.println("thenApply 运行线程: " + Thread.currentThread().getName()); return s + " World"; }); // thenApplyAsync的执行线程 future.thenApplyAsync(s -> { System.out.println("thenApplyAsync 运行线程: " + Thread.currentThread().getName()); return s + " Async"; }, E2); // 关闭执行器 E1.shutdown(); E2.shutdown();
如果supplyAsync未完成时调用后续方法,输出大致如下:
supplyAsync 运行线程: E1-线程 thenApply 运行线程: E1-线程 thenApplyAsync 运行线程: E2-线程
内容的提问来源于stack exchange,提问作者Mooncrater
相关产品推荐
相关产品推荐

