spring中异步任务执行需配置threadpooltaskexecutor bean并用@async注解或手动调用execute/submit方法;须设核心/最大线程数、队列容量、拒绝策略、线程名前缀及优雅关闭;@async方法须public且经spring代理,异常需future.get()捕获,避免事务内直接使用。

在 Spring 中使用 TaskExecutor 实现异步线程池任务执行,核心是配置一个线程池型的 TaskExecutor Bean,并通过 @Async 注解或直接注入调用其 execute() / submit() 方法来提交任务。
配置自定义 ThreadPoolTaskExecutor
Spring 默认提供 SimpleAsyncTaskExecutor(不复用线程),生产环境应替换为基于 JDK 线程池的 ThreadPoolTaskExecutor。推荐在配置类中声明 Bean:
- 设置核心线程数(
corePoolSize)、最大线程数(maxPoolSize)、队列容量(queueCapacity) - 指定拒绝策略(如
CallerRunsPolicy避免丢任务) - 启用线程名称前缀便于日志追踪
- 设置
waitForTasksToCompleteOnShutdown = true确保优雅关闭
示例:
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean("taskExecutor")
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("async-task-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.initialize();
return executor;
}
}
启用 @Async 并指定执行器
在启动类或配置类上添加 @EnableAsync,然后在 Service 方法上标注 @Async。若项目中有多个 TaskExecutor Bean,需显式指定 Bean 名称:
- 无参
@Async使用默认执行器(名为taskExecutor或applicationTaskExecutor) - 带参数如
@Async("taskExecutor")明确绑定到自定义 Bean - 方法返回类型支持
void或Future<t></t>,后者可用于获取结果或异常
示例:
@Service
public class OrderService {
@Async("taskExecutor")
public Future<string> processOrder(Long orderId) {
// 模拟耗时操作
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return new AsyncResult("Order " + orderId + " processed");
}
}
</string>
手动注入并调用 execute/submit
适合需要动态选择执行器、或任务逻辑无法用注解修饰的场景(如 Lambda 表达式、第三方回调):
- 注入已配置的
TaskExecutorBean - 用
execute(Runnable)提交无返回值任务 - 用
submit(Callable<t>)</t>获取Future结果 - 注意:手动调用不经过 Spring AOP 代理,
@Async注解无效
示例:
@Service
public class NotificationService {
@Autowired
private TaskExecutor taskExecutor;
public void sendAsyncNotification(String msg) {
taskExecutor.execute(() -> {
System.out.println("Sending: " + msg + " on thread " + Thread.currentThread().getName());
});
}
}
注意事项与常见问题
实际使用中容易忽略的关键点:
-
@Async方法必须是 public,且调用需经 Spring 代理(不能在同一个类内 self-invocation) - 异常默认被吞掉,若需捕获,用
Future.get()或配置AsyncUncaughtExceptionHandler - 避免在事务方法中直接
@Async,否则新线程不在原事务上下文中(可能需传参或重新开启事务) - 监控线程池状态可暴露
ThreadPoolTaskExecutor的 JMX 或集成 Micrometer 指标
不复杂但容易忽略细节,按需配置执行器 + 正确触发方式 + 合理处理结果和异常,就能稳定支撑业务异步化。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











