Java中CompletionStage/CompletableFuture的默认异步执行设施是什么?
嘿,这个问题问得特别戳痛点——好多人第一次啃Java并发文档时,都会被这个“默认异步执行设施”搞得一头雾水,我来给你理得明明白白:
没错,它就是JVM提供的一个全局共享线程池,绝大多数场景下,那些没指定Executor参数的*Async方法都是靠它干活的。
1. CompletableFuture文档的明确实锤
Java官方文档里其实藏着明确说明,只是可能没被你一眼扫到:
所有未指定显式Executor参数的异步方法均使用ForkJoinPool.commonPool()执行(除非该池不支持至少两个并行级别,在这种情况下,会为每个任务创建一个新的Thread来运行)。
说白了,commonPool是Java 8引入的通用线程池,属于ForkJoinPool的实例,是JVM级别的共享资源,专门用来处理异步非阻塞任务,默认的并行级别是CPU核心数减1(单核心机器则为1)。
2. CompletionStage的模糊性是接口设计的锅
CompletionStage作为一个接口,本身不能硬绑定某个执行器——毕竟得给第三方实现留灵活性。但你完全不用纠结,Java标准库中CompletionStage的唯一实现就是CompletableFuture,所以实际开发中,只要是标准的CompletionStage实例,默认执行设施就是commonPool。
3. 自己动手验证一下(5行代码搞定)
不信的话,跑这段代码试试:
import java.util.concurrent.CompletableFuture; public class DefaultExecutorTest { public static void main(String[] args) { CompletableFuture.runAsync(() -> { System.out.println("当前执行线程:" + Thread.currentThread().getName()); }).join(); } }
输出结果大概率是当前执行线程:ForkJoinPool.commonPool-worker-1,直接实锤用的是commonPool。
4. 极端场景的特殊处理
如果通过JVM参数把commonPool的并行级别设为1(比如-Djava.util.concurrent.ForkJoinPool.common.parallelism=1),这时候它不满足“至少两个并行级别”的要求,CompletableFuture就会为每个*Async任务新建一个独立线程。不过这种场景非常少见,日常开发基本碰不到。
内容的提问来源于stack exchange,提问作者radistao

