Spring 异步与线程池实战全解:失效原因、参数调优与 MQ 选型

很多后端同学在学习并发时都会经历三个阶段:

  1. @Async 用不起来
  2. 线程池参数不会调
  3. 不知道什么时候该用 MQ

如果你也卡在这三点,这篇文章就是为你准备的。

本文将从 实战工程视角,一文打通:

  • @Async 失效原因
  • 线程池参数调优
  • 线程池 vs MQ 选型思维

目标只有一句话:

不只是会用异步,而是理解"什么时候用、怎么用、用到什么程度"。

第一部分:@Async 为什么会失效?

这是 90% 初学者踩的坑。

1. 没有开启异步支持

错误:

java 复制代码
@SpringBootApplication
public class App {}

正确:

java 复制代码
@EnableAsync
@SpringBootApplication
public class App {}

2. 方法不是 public

Spring AOP 代理只能拦截 public 方法。

3. 同类内部调用

java 复制代码
this.sendEmail(); // 无效

必须通过 Spring 注入调用。

4. 默认线程池不可控

如果不自定义线程池:

  • 线程名混乱
  • 并发不可控
  • 容易打爆 CPU

5. 异常被吞掉

异步方法抛出的异常不会自动显示,需要日志或回调处理。

一句话总结:

@Async 不是魔法,本质是 AOP + 线程池。

第二部分:线程池参数怎么调?

线程池不是"越大越好"。

四个核心参数

参数 含义
coreSize 常驻线程
maxSize 最大线程
queueCapacity 排队容量
keepAlive 回收时间

通用经验值

CPU 密集型

java 复制代码
core = CPU 核心数 + 1

IO 密集型

java 复制代码
core = CPU × 2 ~ 3

拒绝策略选择

推荐:

java 复制代码
CallerRunsPolicy

含义:线程池满时让调用方执行,形成削峰。

线程池调优思维

不是凭感觉,而是:

  1. 压测
  2. 观察 CPU
  3. 观察队列堆积
  4. 微调参数

一句话总结:

线程池调优 = 压测 + 观察 + 调整。

第三部分:线程池 vs MQ 怎么选?

很多人会把两者混为一谈。

线程池的定位

适合:

  • 单服务内部并发
  • 写日志
  • 发邮件
  • 图片压缩

关键词:提速

MQ 的定位

适合:

  • 高并发注册
  • 秒杀
  • 订单系统
  • 削峰解耦

关键词:

注册场景拆解

同步主链路:

  • 参数校验
  • 唯一性校验
  • 写用户表

异步旁路:

  • 发短信
  • 发邮件
  • 发券
  • 写日志

一句话记忆:

线程池解决"快",MQ 解决"稳"。

最终总结

后端并发不是:

多开线程

而是:

合理调度资源 + 正确选型。

  1. @Async 解决"用"
  2. 线程池解决"稳"
  3. MQ 解决"系统级并发"

真正的后端工程能力,不在于 API 熟练度,

而在于:

知道什么时候用什么工具。

相关推荐
心在飞扬21 小时前
ReRank重排序提升RAG系统效果
前端·后端
开源之眼21 小时前
《github star 加星 Taimili.com 艾米莉 》为什么Java里面,Service 层不直接返回 Result 对象?
java·后端·github
心在飞扬21 小时前
RAPTOR 递归文档树优化策略
前端·后端
前端Hardy1 天前
别再无脑用 `JSON.parse()` 了!这个安全漏洞你可能每天都在触发
前端·javascript·vue.js
前端Hardy1 天前
别再让 `console.log` 上线了!它正在悄悄拖垮你的生产系统
前端·javascript·vue.js
青青家的小灰灰1 天前
从入门到精通:Vue3 ref vs reactive 最佳实践与底层原理
前端·vue.js·面试
OpenTiny社区1 天前
我的新同事是个AI:支持skill后,它用TinyVue搭项目还挺溜!
前端·vue.js·ai编程
心在飞扬1 天前
MultiVector 多向量检索
前端·后端
用户39051332192881 天前
async 函数返回的 Promise 状态何时变为 resolved
前端
Maori3161 天前
放弃 SDKMAN!在 Garuda Linux + Fish 环境下的优雅 Java 管理指南
java