
SpringBoot使用@Async执行异步方法
说一说Springboot中使用异步@Async注解的一些流程以及注意事项。
1.在主应用类上添加@EnableAsync注解,启用异步支持
@SpringBootApplication
@EnableAsync
public class MyApp {
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
}
}
2.创建一个单独的异步执行类
@Service
public class AsyncService {
@Async
public void asyncMethod() {
// 异步方法的代码
}
}
3.在其他类的方法中调用它
@RestController
public class MyController {
@Autowired
private AsyncService asyncService;
@GetMapping("/test")
public String test() {
// 执行异步任务
asyncService.asyncMethod();
return "ok";
}
}
- ==不要在同一个类中直接调用被@Async注解的方法,因为这会导致方法同步执行。==
- 当一个异步方法B调用另一个异步方法A时,如果A也是异步的,则B的执行不会等待A完成。
- 在异步方法中,事务会被异步地传播,这意味着如果父事务回滚,子事务(即异步方法)可能不会回滚。
==还要注意:==
当使用@Async注解时,默认情况下会使用一个简单的SimpleAsyncTaskExecutor来执行异步方法。但是,SimpleAsyncTaskExecutor并不是真正的线程池,它每次执行都会创建一个新的线程,这可能会导致系统资源耗尽,单机情况可以采用默认,但高并发情况推荐自定义创建一个线程池,例如创建一个“taskExecutor”名字的线程池。
@Configuration
@EnableAsync
public class ThreadPoolConfig {
@Bean(name = "taskExecutor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5); // 核心线程数,最小存活
executor.setMaxPoolSize(10); // 允许最大线程数
executor.setQueueCapacity(25); // 队列容量
executor.setThreadNamePrefix("Async-"); // 线程名前缀
executor.initialize();
return executor;
}
}
@Service
public class AsyncService {
@Async("taskExecutor")
public void asyncMethod() {
// 这里将会使用注入的taskExecutor线程池执行异步方法
}
}
只需要在@Async中指定线程池名称即可,
当然,也可以全局配置,比如在启动类@EnableAsync注解中指定默认的线程池Bean名称
@SpringBootApplication
@EnableAsync("taskExecutor")
public class MyApp {}
//后续 @Async可省略bean名称
@Async
public void asyncMethod() {}
异步方法返回类型问题:
如果异步方法的返回类型不是void,调用者得到的将是代表异步操作的Future,而不是操作的实际结果。
@Async
public Future<String> asyncMethod() {}
目录