当前位置: 首页 > news >正文

Spring Boot 优雅实现异步调用:从入门到自定义线程池与异常处理

在 Spring Boot 项目里,同步接口经常会被慢接口拖垮响应速度。异步调用可以把耗时任务丢到独立线程,让主线程快速返回,提升接口吞吐量与用户体验。

这篇文章用最清晰、最工程化的方式,带你从零学会 Spring Boot 异步开发,包含默认使用、自定义线程池、异常处理、避坑要点。


一、先搞懂:同步 vs 异步

  • 同步:任务串行执行,必须等上一个完成才能走下一个,主线程阻塞。
  • 异步:任务提交给独立线程执行,主线程不用等,直接返回。

适用场景:

  • 发送短信、推送消息
  • 记录日志、上报埋点
  • 调用第三方慢接口
  • 批量数据处理

二、Spring Boot 异步最简实现(3步搞定)

Spring 提供@Async+@EnableAsync开箱即用。

1. 启动类/配置类开启异步

@SpringBootApplication @EnableAsync // 开启异步 public class AsyncApplication { public static void main(String[] args) { SpringApplication.run(AsyncApplication.class, args); } }

2. 编写异步 Service

规则

  • 方法必须是public
  • 不能是本类内部调用(AOP 代理限制)
  • 返回值只能是voidFuture<T>
@Service @Slf4j public class AsyncServiceImpl { // 无返回值异步 @Async public void asyncVoidTask() throws InterruptedException { Thread.sleep(3000); log.info("异步任务执行,线程:{}", Thread.currentThread().getName()); } // 带返回值异步 @Async public Future<String> asyncFutureTask() throws InterruptedException { Thread.sleep(5000); log.info("异步任务执行,线程:{}", Thread.currentThread().getName()); return new AsyncResult<>("任务执行完成"); } }

3. Controller 调用

@RestController @Slf4j public class AsyncController { @Autowired private AsyncServiceImpl asyncService; @GetMapping("/async/void") public String testVoid() { long start = System.currentTimeMillis(); log.info("主线程:{}", Thread.currentThread().getName()); asyncService.asyncVoidTask(); return "耗时:" + (System.currentTimeMillis() - start) + "ms"; } @GetMapping("/async/future") public String testFuture() throws ExecutionException, InterruptedException { long start = System.currentTimeMillis(); Future<String> future = asyncService.asyncFutureTask(); // 阻塞获取结果 String result = future.get(); return result + ",总耗时:" + (System.currentTimeMillis() - start) + "ms"; } }

运行结果

  • /async/void:立即返回,耗时几毫秒,异步任务后台执行。
  • /async/future:会阻塞 5 秒,但依然是异步执行。

三、自定义异步线程池(生产必须用)

Spring 默认用SimpleAsyncTaskExecutor,不重用线程,高并发会OOM。生产环境必须自定义线程池

@Configuration public class AsyncConfig implements AsyncConfigurer { @Override @Bean("asyncTaskExecutor") public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); // 核心线程数 executor.setCorePoolSize(5); // 最大线程数 executor.setMaxPoolSize(10); // 队列容量 executor.setQueueCapacity(200); // 线程名前缀 executor.setThreadNamePrefix("async-task-"); // 关机时等待任务完成 executor.setWaitForTasksToCompleteOnShutdown(true); // 等待时长 executor.setAwaitTerminationSeconds(60); // 拒绝策略 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.initialize(); return executor; } }

使用时指定线程池:

@Async("asyncTaskExecutor") public void asyncVoidTask() { ... }

四、自定义异步异常处理器

异步方法里抛异常,主线程感知不到。我们可以统一捕获。

@Configuration public class AsyncConfig implements AsyncConfigurer { // 上面的线程池配置... @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return (ex, method, params) -> { log.error("异步方法异常:{}", method.getName()); log.error("异常信息:", ex); }; } }

效果:
异步任务报错后,不会直接吞掉,会按你定义的方式打印/告警。


五、@Async 工作原理(面试常问)

  1. @EnableAsync开启 AOP 代理。
  2. @Async方法被调用时,Spring 拦截并提交到线程池。
  3. 由线程池里的线程执行目标方法。
  4. 主线程立即返回,不阻塞。

六、避坑指南(非常重要)

  1. 异步方法必须是 public,private 不生效。
  2. 不能同类内部调用,比如this.asyncMethod(),不走代理。
  3. 返回值只能是 void / Future,用ListenableFuture也可以。
  4. 生产必须自定义线程池,默认会无限创建线程。
  5. 异常必须单独处理,主线程 catch 不到。
  6. 事务不生效:异步方法和主线程不在一个事务里。

七、总结

Spring Boot 异步非常简单:

  • 开启:@EnableAsync
  • 标记:@Async
  • 生产:自定义线程池 + 异常处理
  • 场景:耗时、非核心、可并行任务

用好异步,能让你的接口性能直接上一个台阶。

降重鸟技术团队文章,勿全文转发

http://www.jsqmd.com/news/706183/

相关文章:

  • 论文阅读:ICLR 2026 AlphaAlign: Incentivizing Safety Alignment with Extremely Simplified Reinforcement Le
  • 如何快速提升麻将水平:终极雀魂AI助手Akagi完整指南
  • 深度强化学习实战:从DQN到PPO的算法实现与调参指南
  • 卷烟卷接包产线CPM1A控制器以太网化改造:一机多联通讯架构设计
  • 【限时开放】Docker官方2026安全基线评估工具(非开源版)内测资格仅剩47席:自动扫描你的AI训练镜像是否存在LLM提示注入残留、权重后门及CUDA驱动提权路径
  • R语言描述性统计:数据分析第一步与实战技巧
  • 基于LangChain与Azure OpenAI构建智能问答云函数实战指南
  • 一文吃透微服务:从单体到RPC、服务治理、下一代架构Service Mesh
  • 探索论文写作新宇宙:书匠策AI,毕业论文的“星际导航员”!
  • Akagi麻雀助手:终极指南 - 如何用AI提升你的雀魂麻将水平
  • Spring Boot AOP 面向切面编程:从原理到实战,一篇就会
  • Go语言怎么做AES加密_Go语言AES加密解密教程【精选】
  • 基于安卓的快递包裹隐私保护系统毕业设计源码
  • OpenCV中SVM算法原理与图像分类实战
  • 广西广告标识源头厂家哪家好?深度对比TOP10榜单揭晓 - 速递信息
  • AI模型推理沙箱化实践(Docker+gVisor+eBPF三重加固方案)
  • 手把手教你搞定移远EC200U/EC25的Linux驱动:从硬件检查到串口映射的保姆级教程
  • JeecgBoot企业级低代码平台:Spring Boot+Vue3架构解析与实战指南
  • 广西靠谱的标识标牌源头厂家推荐:从案例看巨匠标识的实力 - 速递信息
  • 2026专业上海公考教育推荐榜:上海法考课程、上海公考培训、上海公考教学、上海公考教育机构、上海公考机构、上海公考课程选择指南 - 优质品牌商家
  • 【国家药监局NMPA备案强制要求】:MCP 2026脱敏配置必须启用的3项不可绕过参数(含审计日志生成逻辑)
  • 如何了解imtoken钱包是什么 - 速递信息
  • 2026佛山代运营公司口碑真实测评 佛山短视频代运营最新TOP3榜单 - 速递信息
  • 现代相机成像基本流程
  • OpenContext:为AI编程助手打造持久记忆,实现上下文无缝管理
  • 在语雀客户端中,个人、空间、知识库怎么区分使用
  • redis中缓存穿透,及解决方案
  • 湖南大奥之心:长沙奥迪专修标杆,让每台德系车重焕新生 - 速递信息
  • 2026哈尔滨偏瘫无法行走:哈尔滨偏瘫肢体麻木、哈尔滨偏瘫行动障碍、哈尔滨偏瘫语言障碍、哈尔滨冠心病室上速、哈尔滨冠心病心律不齐选择指南 - 优质品牌商家
  • 中医智能诊疗系统-阶段一