目录
1. 核心注解:@Async
2. 基础使用示例
(1)启用异步支持
(2)定义异步方法
(3)调用异步方法
3. 高级配置
(1)自定义线程池
(2)指定线程池执行器
4. 返回值处理
(1)无返回值
(2)有返回值
5. 常见问题与解决
(1)异步方法不生效
(2)线程池配置无效
(3)异常处理
6. 适用场景
7.总结
Spring 框架中用于实现异步方法调用的注解是 @Async
。这个注解允许方法在独立的线程中异步执行,从而避免阻塞主线程,提升系统吞吐量和响应速度。
1. 核心注解:@Async
- 作用:标记一个方法为异步执行,Spring 会通过线程池启动新线程执行该方法。
- 使用条件:
-
- 在 Spring Boot 启动类或配置类上添加
@EnableAsync
启用异步支持。 - 异步方法必须定义在 Spring管理的Bean中(如
@Service
、@Component
注解的类)。 - 调用异步方法时,需通过 Spring代理对象调用(直接调用同类中的异步方法会失效)。(这一点和事务失效的一种情况有点相似)
- 在 Spring Boot 启动类或配置类上添加
2. 基础使用示例
(1)启用异步支持
@SpringBootApplication
@EnableAsync //启用异步支持
public class Application {public static void main(String[] args) {SpringApplication.run(MyApplication.class, args);}
}
(2)定义异步方法
@Service
public class MyService {@Async // 标记为异步方法public void asyncTask() {// 模拟耗时操作System.out.println("异步任务执行线程: " + Thread.currentThread().getName());}public void syncTask() {System.out.println("同步任务执行线程: " + Thread.currentThread().getName());}
}
(3)调用异步方法
@RestController
public class MyController {@Autowiredprivate MyService myService;@GetMapping("/test-async")public String testAsync() {myService.asyncTask(); //异步执行myService.syncTask(); //同步执行return "Check console logs!";}
}
输出结果:
异步任务执行线程: task-1
同步任务执行线程: http-nio-8080-exec-1
3. 高级配置
(1)自定义线程池
默认情况下,Spring 使用 SimpleAsyncTaskExecutor
(非池化线程),建议自定义线程池:
@Configuration
public class AsyncConfig {@Bean(name = "myTaskExecutor")public Executor taskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(5);executor.setMaxPoolSize(10);executor.setQueueCapacity(100);executor.setThreadNamePrefix("MyAsyncThread-");executor.initialize();return executor;}
}
(2)指定线程池执行器
@Async("myTaskExecutor") // 指定使用自定义线程池
public void asyncTaskWithCustomPool() {//业务逻辑
}
4. 返回值处理
(1)无返回值
直接使用 void
:
@Async
public void asyncVoidMethod() { /* ... */ }
(2)有返回值
返回 Future
或 CompletableFuture
:
@Async
public Future<String> asyncFutureMethod() {return new AsyncResult<>("Task result");
}
@Async
public CompletableFuture<String> asyncCompletableFutureMethod() {return CompletableFuture.completedFuture("Task result");
}
调用示例:
Future<String> future = myService.asyncFutureMethod();
String result = future.get(); // 阻塞等待结果
5. 常见问题与解决
(1)异步方法不生效
- 原因:未启用
@EnableAsync
,或方法未通过代理对象调用。 - 解决:
-
- 确保启动类添加
@EnableAsync
。 - 避免同类内部调用异步方法(如
this.asyncTask()
)。
- 确保启动类添加
(2)线程池配置无效
- 原因:未正确注入自定义线程池。
- 解决:检查
@Async("beanName")
中的 Bean 名称是否匹配。
(3)异常处理
异步方法默认不传播异常到调用方,需通过 AsyncUncaughtExceptionHandler
处理:
@Configuration
public class AsyncConfig implements AsyncConfigurer {@Overridepublic Executor getAsyncExecutor() {//返回自定义线程池}@Overridepublic AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {return (ex, method, params) -> {System.err.println("异步方法异常: " + method.getName());ex.printStackTrace();};}
}
6. 适用场景
- 耗时操作:发送邮件、生成报表、调用外部 API。
- 非关键路径任务:日志记录、数据缓存更新。
- 高并发优化:减少请求响应时间,提升吞吐量。
7.总结
- 核心注解:
@Async
+@EnableAsync
。 - 关键配置:自定义线程池、异常处理。
- 注意事项:避免同类调用、合理控制线程池参数。
通过合理使用 @Async
,可以显著提升 Spring 应用的并发处理能力。