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

Spring Boot应用执行@Async方法后关闭时挂起问题求助

Spring Boot应用关闭挂起问题(@Async + ApplicationRunner场景)

问题背景

实现ApplicationRunner的Spring Boot应用在关闭时出现挂起:所有带@Async注解的任务已执行完成,但最后一次System.out.println()调用后,应用仍需延迟一段时间才会终止。该问题在Linux Mint(Open-JDK 17.0.7)和树莓派环境下均可复现,存在完整演示项目。

解决方案

1. 自定义异步线程池并配置优雅关闭

Spring Boot默认的@Async线程池未配置优雅关闭策略,导致应用关闭时需等待线程超时退出。自定义线程池并设置任务等待与超时参数:

@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(4);
        executor.setMaxPoolSize(8);
        executor.setQueueCapacity(10);
        executor.setThreadNamePrefix("Async-Worker-");
        // 关闭时等待所有已提交任务完成
        executor.setWaitForTasksToCompleteOnShutdown(true);
        // 设置最大等待超时时间(按需调整,示例为10秒)
        executor.setAwaitTerminationSeconds(10);
        executor.initialize();
        return executor;
    }
}

2. 在ApplicationRunner中手动等待异步任务完成

若不想修改线程池,可在ApplicationRunner中跟踪所有异步任务的Future对象,等待全部完成后再结束流程:

@Component
public class MainComponent implements ApplicationRunner {
    private final JobsService jobsService;
    private final List<Future<?>> asyncTasks = new ArrayList<>();

    public MainComponent(JobsService jobsService) {
        this.jobsService = jobsService;
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        // 提交异步任务并保存Future引用
        asyncTasks.add(jobsService.asyncJob1());
        asyncTasks.add(jobsService.asyncJob2());
        
        // 等待所有任务执行完成
        for (Future<?> task : asyncTasks) {
            task.get();
        }

        System.out.println("所有任务执行完毕,应用即将关闭");
    }
}

3. 排查异步方法中的未释放资源

检查@Async注解的方法是否持有未关闭的资源(如数据库连接、文件IO流、网络连接等),此类资源可能导致线程无法正常终止,进而引发应用挂起。

原因解析

Spring Boot关闭时会触发上下文销毁流程:

  • 默认@Async使用的SimpleAsyncTaskExecutor会创建非守护线程,JVM需等待所有非守护线程终止才会退出;
  • 即使任务执行完成,空闲线程仍需等待超时才会销毁,导致应用出现挂起延迟;
  • 自定义线程池配置优雅关闭后,Spring会在上下文销毁时等待线程池内任务完成,并在超时后强制终止线程,避免长时间挂起。

内容的提问来源于stack exchange,提问作者D-Dᴙum

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 21:52:35