登录社区云,与社区用户共同成长
邀请您加入社区
System.out.println("[" + Thread.currentThread().getName() + "] 审计日志已记录: " + log.getAction());logger.error("异步方法执行失败: {}.{}", method.getDeclaringClass().getName(), method.getName(), ex);System.err.prin
快速入门
启用异步支持
在 Spring Boot 应用中,首先需要在配置类上添加 @EnableAsync 注解来开启异步功能:
@Configuration
@EnableAsync
public class AsyncConfig {
// 可在此自定义线程池
}
标记异步方法
在需要异步执行的方法上添加 @Async 注解:
@Service
public class NotificationService {
// 无返回值的异步方法
@Async
public void sendEmail(String email) {
// 模拟耗时操作
try {
Thread.sleep(3000);
System.out.println("邮件已发送至: " + email);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
// 有返回值的异步方法
public Future processData(String input) {
Thread.sleep(2000);
String result = "处理结果: " + input.toUpperCase();
return new AsyncResult<>(result);
return new AsyncResult<>("处理失败");
调用异步方法
@RestController
public class DemoController {
@Autowired
private NotificationService notificationService;
@GetMapping("/send")
public String sendEmail() {
notificationService.sendEmail("user@example.com");
return "请求已接受,处理中...";
@GetMapping("/process")
public String processData() throws Exception {
Future future = notificationService.processData("hello");
// 执行其他任务...
String result = future.get(); // 阻塞获取结果
return result;
实现原理
核心机制:AOP 与代理模式
Spring 的 @Async 功能基于 AOP(面向切面编程)和代理模式实现:
启用阶段:@EnableAsync 导入配置,注册 AsyncAnnotationBeanPostProcessor
处理阶段:后处理器检查 Bean 方法上的 @Async 注解,并创建代理对象
执行阶段:代理对象拦截方法调用,将执行提交给 TaskExecutor
源码解析
核心拦截器 AnnotationAsyncExecutionInterceptor 的 invoke 方法:
public Object invoke(final MethodInvocation invocation) throws Throwable {
// 确定使用的执行器
Executor executor = getExecutor(this.beanFactory, invocation.getMethod());
// 将方法调用封装为 Callable 任务
Callable task = () -> { try { Object result = invocation.proceed(); // 执行原始方法 if (result instanceof Future) { return ((Future) result).get(); } } catch (Throwable ex) { handleError(ex, invocation.getMethod(), invocation.getArguments()); } return null; }; // 提交给执行器执行 return doSubmit(task, executor, invocation.getMethod().getReturnType()); } 返回值处理逻辑在 doSubmit 方法中: protected Object doSubmit(Callable task, AsyncTaskExecutor executor, Class returnType) { if (CompletableFuture.class.isAssignableFrom(returnType)) { return CompletableFuture.supplyAsync(() -> { try { return task.call(); } catch (Throwable ex) { throw new CompletionException(ex); } }, executor); } else if (ListenableFuture.class.isAssignableFrom(returnType)) { return ((AsyncListenableTaskExecutor) executor).submitListenable(task); } else if (Future.class.isAssignableFrom(returnType)) { return executor.submit(task); } else { executor.submit(task); // 非Future类型,提交后返回null return null; } } 默认配置 Spring Boot 的自动化配置 Spring Boot 通过 TaskExecutionAutoConfiguration 自动配置线程池,默认参数如下: 配置项 默认值 说明 核心线程数 8 即使空闲也会保留的线程数 最大线程数 Integer.MAX_VALUE 线程池可创建的最大线程数 队列容量 Integer.MAX_VALUE 使用无界LinkedBlockingQueue 线程空闲时间 60秒 超出核心线程数的空闲线程存活时间 线程名称前缀 "task-" 线程名称的前缀 拒绝策略 AbortPolicy 抛出RejectedExecutionException 配置属性映射 Spring Boot 将这些配置映射到 application.properties: # 线程池配置 spring.task.execution.pool.core-size=8 spring.task.execution.pool.max-size=2147483647 spring.task.execution.pool.queue-capacity=2147483647 spring.task.execution.pool.keep-alive=60s spring.task.execution.thread-name-prefix=task- 与纯 Spring 的差异 环境 默认执行器 特点 适用场景 纯 Spring SimpleAsyncTaskExecutor 无线程池,每次创建新线程 不适用于生产环境 Spring Boot ThreadPoolTaskExecutor 固定核心线程+无界队列 开发测试环境 最佳实践 1. 自定义线程池配置 生产环境必须自定义线程池参数: @Configuration @EnableAsync public class AsyncConfig { @Bean(name = "taskExecutor") public Executor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); // 核心配置 executor.setCorePoolSize(10); executor.setMaxPoolSize(25); executor.setQueueCapacity(100); // 使用有界队列 executor.setKeepAliveSeconds(30); // 线程配置 executor.setThreadNamePrefix("App-Async-"); executor.setThreadPriority(Thread.NORM_PRIORITY); // 拒绝策略 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 关闭设置 executor.setWaitForTasksToCompleteOnShutdown(true); executor.setAwaitTerminationSeconds(60); executor.initialize(); return executor; } } 2. 异常处理 异步方法中的异常不会自动传播,需要专门处理: @Configuration @EnableAsync public class AsyncConfig implements AsyncConfigurer { @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return (ex, method, params) -> { // 记录日志、发送警报等 logger.error("异步方法执行失败: {}.{}", method.getDeclaringClass().getName(), method.getName(), ex); alertService.sendAlert("异步任务异常", ex.getMessage()); }; } } 3. 使用 CompletableFuture Java 8+ 推荐使用 CompletableFuture 作为返回值: @Async public CompletableFuture asyncProcess(String input) { return CompletableFuture.supplyAsync(() -> { // 业务逻辑 return processInput(input); }, taskExecutor); } 4. 实际应用案例 日志记录场景的异步处理: @Service public class AuditLogService { @Async("taskExecutor") public void logAction(AuditLog log) { try { // 模拟耗时的日志存储操作 auditRepository.save(log); System.out.println("[" + Thread.currentThread().getName() + "] 审计日志已记录: " + log.getAction()); } catch (Exception e) { System.err.println("记录审计日志失败: " + e.getMessage()); // 可加入重试逻辑 } } } @RestController public class BusinessController { @Autowired private AuditLogService auditLogService; @PostMapping("/business-action") public ResponseEntity performBusinessAction(@RequestBody ActionRequest request) { // 执行核心业务逻辑 BusinessResult result = businessService.execute(request); // 异步记录审计日志,不影响主流程响应速度 AuditLog log = new AuditLog(); log.setUserId(request.getUserId()); log.setAction(request.getActionType()); log.setTimestamp(LocalDateTime.now()); auditLogService.logAction(log); return ResponseEntity.ok(result); } } 总结 Spring Boot 中的 @Async 注解提供了强大的异步处理能力,但其默认配置可能不适合高并发生产环境。理解其工作原理和默认行为对于正确使用这一功能至关重要。 关键要点 始终自定义线程池:不要依赖默认配置,特别是无界队列设置 合理设置线程池参数:根据业务类型(CPU/IO密集型)调整核心配置 正确处理异常:实现 AsyncUncaughtExceptionHandler 处理异步异常 使用合适的返回值:优先选择 CompletableFuture 作为返回值类型 监控线程池状态:生产环境中需要监控线程池的运行指标 通过遵循这些最佳实践,您可以充分利用 @Async 的优势,构建出高性能、高可靠的异步处理系统。
Object result = invocation.proceed(); // 执行原始方法
if (result instanceof Future) {
return ((Future) result).get();
catch (Throwable ex) {
handleError(ex, invocation.getMethod(), invocation.getArguments());
return null;
};
// 提交给执行器执行
return doSubmit(task, executor, invocation.getMethod().getReturnType());
返回值处理逻辑在 doSubmit 方法中:
protected Object doSubmit(Callable task, AsyncTaskExecutor executor, Class returnType) { if (CompletableFuture.class.isAssignableFrom(returnType)) { return CompletableFuture.supplyAsync(() -> { try { return task.call(); } catch (Throwable ex) { throw new CompletionException(ex); } }, executor); } else if (ListenableFuture.class.isAssignableFrom(returnType)) { return ((AsyncListenableTaskExecutor) executor).submitListenable(task); } else if (Future.class.isAssignableFrom(returnType)) { return executor.submit(task); } else { executor.submit(task); // 非Future类型,提交后返回null return null; } } 默认配置 Spring Boot 的自动化配置 Spring Boot 通过 TaskExecutionAutoConfiguration 自动配置线程池,默认参数如下: 配置项 默认值 说明 核心线程数 8 即使空闲也会保留的线程数 最大线程数 Integer.MAX_VALUE 线程池可创建的最大线程数 队列容量 Integer.MAX_VALUE 使用无界LinkedBlockingQueue 线程空闲时间 60秒 超出核心线程数的空闲线程存活时间 线程名称前缀 "task-" 线程名称的前缀 拒绝策略 AbortPolicy 抛出RejectedExecutionException 配置属性映射 Spring Boot 将这些配置映射到 application.properties: # 线程池配置 spring.task.execution.pool.core-size=8 spring.task.execution.pool.max-size=2147483647 spring.task.execution.pool.queue-capacity=2147483647 spring.task.execution.pool.keep-alive=60s spring.task.execution.thread-name-prefix=task- 与纯 Spring 的差异 环境 默认执行器 特点 适用场景 纯 Spring SimpleAsyncTaskExecutor 无线程池,每次创建新线程 不适用于生产环境 Spring Boot ThreadPoolTaskExecutor 固定核心线程+无界队列 开发测试环境 最佳实践 1. 自定义线程池配置 生产环境必须自定义线程池参数: @Configuration @EnableAsync public class AsyncConfig { @Bean(name = "taskExecutor") public Executor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); // 核心配置 executor.setCorePoolSize(10); executor.setMaxPoolSize(25); executor.setQueueCapacity(100); // 使用有界队列 executor.setKeepAliveSeconds(30); // 线程配置 executor.setThreadNamePrefix("App-Async-"); executor.setThreadPriority(Thread.NORM_PRIORITY); // 拒绝策略 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 关闭设置 executor.setWaitForTasksToCompleteOnShutdown(true); executor.setAwaitTerminationSeconds(60); executor.initialize(); return executor; } } 2. 异常处理 异步方法中的异常不会自动传播,需要专门处理: @Configuration @EnableAsync public class AsyncConfig implements AsyncConfigurer { @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return (ex, method, params) -> { // 记录日志、发送警报等 logger.error("异步方法执行失败: {}.{}", method.getDeclaringClass().getName(), method.getName(), ex); alertService.sendAlert("异步任务异常", ex.getMessage()); }; } } 3. 使用 CompletableFuture Java 8+ 推荐使用 CompletableFuture 作为返回值: @Async public CompletableFuture asyncProcess(String input) { return CompletableFuture.supplyAsync(() -> { // 业务逻辑 return processInput(input); }, taskExecutor); } 4. 实际应用案例 日志记录场景的异步处理: @Service public class AuditLogService { @Async("taskExecutor") public void logAction(AuditLog log) { try { // 模拟耗时的日志存储操作 auditRepository.save(log); System.out.println("[" + Thread.currentThread().getName() + "] 审计日志已记录: " + log.getAction()); } catch (Exception e) { System.err.println("记录审计日志失败: " + e.getMessage()); // 可加入重试逻辑 } } } @RestController public class BusinessController { @Autowired private AuditLogService auditLogService; @PostMapping("/business-action") public ResponseEntity performBusinessAction(@RequestBody ActionRequest request) { // 执行核心业务逻辑 BusinessResult result = businessService.execute(request); // 异步记录审计日志,不影响主流程响应速度 AuditLog log = new AuditLog(); log.setUserId(request.getUserId()); log.setAction(request.getActionType()); log.setTimestamp(LocalDateTime.now()); auditLogService.logAction(log); return ResponseEntity.ok(result); } } 总结 Spring Boot 中的 @Async 注解提供了强大的异步处理能力,但其默认配置可能不适合高并发生产环境。理解其工作原理和默认行为对于正确使用这一功能至关重要。 关键要点 始终自定义线程池:不要依赖默认配置,特别是无界队列设置 合理设置线程池参数:根据业务类型(CPU/IO密集型)调整核心配置 正确处理异常:实现 AsyncUncaughtExceptionHandler 处理异步异常 使用合适的返回值:优先选择 CompletableFuture 作为返回值类型 监控线程池状态:生产环境中需要监控线程池的运行指标 通过遵循这些最佳实践,您可以充分利用 @Async 的优势,构建出高性能、高可靠的异步处理系统。
if (CompletableFuture.class.isAssignableFrom(returnType)) {
return CompletableFuture.supplyAsync(() -> {
return task.call();
} catch (Throwable ex) {
throw new CompletionException(ex);
}, executor);
else if (ListenableFuture.class.isAssignableFrom(returnType)) {
return ((AsyncListenableTaskExecutor) executor).submitListenable(task);
else if (Future.class.isAssignableFrom(returnType)) {
return executor.submit(task);
else {
executor.submit(task); // 非Future类型,提交后返回null
默认配置
Spring Boot 的自动化配置
Spring Boot 通过 TaskExecutionAutoConfiguration 自动配置线程池,默认参数如下:
配置项 默认值 说明
核心线程数 8 即使空闲也会保留的线程数
最大线程数 Integer.MAX_VALUE 线程池可创建的最大线程数
队列容量 Integer.MAX_VALUE 使用无界LinkedBlockingQueue
线程空闲时间 60秒 超出核心线程数的空闲线程存活时间
线程名称前缀 "task-" 线程名称的前缀
拒绝策略 AbortPolicy 抛出RejectedExecutionException
配置属性映射
Spring Boot 将这些配置映射到 application.properties:
# 线程池配置
spring.task.execution.pool.core-size=8
spring.task.execution.pool.max-size=2147483647
spring.task.execution.pool.queue-capacity=2147483647
spring.task.execution.pool.keep-alive=60s
spring.task.execution.thread-name-prefix=task-
与纯 Spring 的差异
环境 默认执行器 特点 适用场景
纯 Spring SimpleAsyncTaskExecutor 无线程池,每次创建新线程 不适用于生产环境
Spring Boot ThreadPoolTaskExecutor 固定核心线程+无界队列 开发测试环境
最佳实践
1. 自定义线程池配置
生产环境必须自定义线程池参数:
@Bean(name = "taskExecutor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 核心配置
executor.setCorePoolSize(10);
executor.setMaxPoolSize(25);
executor.setQueueCapacity(100); // 使用有界队列
executor.setKeepAliveSeconds(30);
// 线程配置
executor.setThreadNamePrefix("App-Async-");
executor.setThreadPriority(Thread.NORM_PRIORITY);
// 拒绝策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 关闭设置
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(60);
executor.initialize();
return executor;
2. 异常处理
异步方法中的异常不会自动传播,需要专门处理:
public class AsyncConfig implements AsyncConfigurer {
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return (ex, method, params) -> {
// 记录日志、发送警报等
logger.error("异步方法执行失败: {}.{}", method.getDeclaringClass().getName(), method.getName(), ex);
alertService.sendAlert("异步任务异常", ex.getMessage());
3. 使用 CompletableFuture
Java 8+ 推荐使用 CompletableFuture 作为返回值:
public CompletableFuture asyncProcess(String input) {
// 业务逻辑
return processInput(input);
}, taskExecutor);
4. 实际应用案例
日志记录场景的异步处理:
public class AuditLogService {
@Async("taskExecutor")
public void logAction(AuditLog log) {
// 模拟耗时的日志存储操作
auditRepository.save(log);
System.out.println("[" + Thread.currentThread().getName() + "] 审计日志已记录: " + log.getAction());
} catch (Exception e) {
System.err.println("记录审计日志失败: " + e.getMessage());
// 可加入重试逻辑
public class BusinessController {
private AuditLogService auditLogService;
@PostMapping("/business-action")
public ResponseEntity performBusinessAction(@RequestBody ActionRequest request) {
// 执行核心业务逻辑
BusinessResult result = businessService.execute(request);
// 异步记录审计日志,不影响主流程响应速度
AuditLog log = new AuditLog();
log.setUserId(request.getUserId());
log.setAction(request.getActionType());
log.setTimestamp(LocalDateTime.now());
auditLogService.logAction(log);
return ResponseEntity.ok(result);
总结
Spring Boot 中的 @Async 注解提供了强大的异步处理能力,但其默认配置可能不适合高并发生产环境。理解其工作原理和默认行为对于正确使用这一功能至关重要。
关键要点
始终自定义线程池:不要依赖默认配置,特别是无界队列设置
合理设置线程池参数:根据业务类型(CPU/IO密集型)调整核心配置
正确处理异常:实现 AsyncUncaughtExceptionHandler 处理异步异常
使用合适的返回值:优先选择 CompletableFuture 作为返回值类型
监控线程池状态:生产环境中需要监控线程池的运行指标
通过遵循这些最佳实践,您可以充分利用 @Async 的优势,构建出高性能、高可靠的异步处理系统。
有“AI”的1024 = 2048,欢迎大家加入2048 AI社区
更多推荐
大模型文本分割实战指南:Chonkie、LangChain、LlamaIndex工具详解与代码实现!
不惧AI查重!这12个「降AI率」工具,让你作业、论文瞬间「去AI化」!
看看睦AI从零开始系列教程03 - Prompt提示语学习与应用w
之所以出现这个现象,根本原因是上面说的方法都是基于外部检测的,天然有随机性的问题,因为外部检测都需要定时轮询,所以系统可能已经出问题了,但是却需要等到下一个检测发起执行语句的时候,才有可能发现问题。InnoDB将该参数的默认值设为0,但不限制并发线程数实际上是不行的,因为一个机器的CPU核数有限,线程全进来会有很大的上下文切换成本。如果处于锁等待状态的线程计数不减1,InnoDB会认为线程数用满,
扫一扫分享内容
所有评论(0)