You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java主线程外异步计算是否每次需新建ExecutorService?与JS差异原因?

Java CompletableFuture 异步执行问题解答

问题相关代码示例

示例1:自定义ExecutorService的异步代码

public void run (String[] args) throws Exception
{
    System.out.println("testing async");
    
    ExecutorService ex = Executors.newFixedThreadPool(10);
    
    CompletableFuture.supplyAsync(()->
    {
        return secondfunc("");
    }, ex).thenApply( (val)->
    {                                                    
        return secondfunc(val);
    }).thenApply( (val) -> 
    {
        return thirdfunc(val);
    }).thenAccept((val)->
    {
        System.out.println(val);
        ex.shutdown();
    });
    
    System.out.println("done testing async");                
}

示例1输出

testing async
done testing async
200 200 -->println from fisrt method
200 200 -->println from second method
200 200 -->println from third method
Done Post twoDone Post twoDone Post three -->result on the accept

示例2:使用默认线程池的异步代码

public void run (String[] args) throws Exception
{
    System.out.println("testing async");
   
    
    CompletableFuture.supplyAsync(()->
    {
        return secondfunc("");
    }).thenApply( (val)->
    {                                                    
        return secondfunc(val);
    }).thenApply( (val) -> 
    {
        return thirdfunc(val);
    }).thenAccept((val)->
    {
        System.out.println(val);
    });
    
    System.out.println("done testing async");                
}

示例2输出

testing async
done testing async

问题解答

1. Java执行主线程外的异步计算是否每次都需要创建ExecutorService?

不需要:

  • CompletableFuture的supplyAsync、runAsync等方法如果不传Executor参数,会默认使用JDK自带的全局公共线程池ForkJoinPool.commonPool(),无需每次自行创建线程池。
  • 示例2没有输出后续异步任务日志的原因是:公共ForkJoinPool里的线程默认都是守护线程,JVM进程终止的条件是所有非守护线程全部执行结束,示例2中主线程(非守护线程)执行完最后一行打印后直接退出,JVM不会等待守护线程里的异步任务执行完成,所以后续日志没有输出。
  • 生产环境更建议自定义ExecutorService而非使用公共池:公共池是全局共享的,多个业务共用容易出现资源争抢、互相影响的问题,自定义线程池可以灵活配置线程数、线程名、异常处理策略、拒绝策略等,也可以自主控制线程是否为守护线程。同时自定义线程池支持全局复用,不需要每次执行异步任务都新建。

2. 该场景下Java的异步表现为什么和JavaScript存在差异?

二者的异步运行模型完全不同:

  • Java的异步基于多线程实现,JVM进程的生命周期和非守护线程绑定,主线程退出后如果没有其他非守护线程运行,进程会直接终止,未完成的守护线程任务会被直接中断丢弃。
  • JavaScript是单线程事件循环模型,只要异步任务还在等待执行(比如定时器、IO回调、Promise回调未触发),事件循环就不会停止,进程(Node.js场景)或者页面上下文(浏览器场景)就不会主动退出,除非手动终止进程/关闭页面,所以JS里的异步任务只要没有报错,基本都会执行完成。

内容的提问来源于stack exchange,提问作者Leandro Gamarra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 00:18:04