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
//如果在主类文件MyApp中添加了下面注解,就不需要了,全局一个就行
//@EnableAsync
public class ThreadPoolConfig {
@Bean(name = "taskExecutor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2); // 核心线程数
executor.setQueueCapacity(20); // 队列容量
executor.setMaxPoolSize(5); // 最大线程数
//并发情况,先走核心线程,然后走队列,满了再创建最大线程数。总数也就是2+20+5
executor.setAllowCoreThreadTimeOut(true);//允许核心线程超时销毁
executor.setKeepAliveSeconds(60); // 设置空闲线程的存活时间
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());//拒绝策略,丢弃旧任务
executor.setThreadNamePrefix("Async-");
executor.initialize();
return executor;
}
}
可以在方法中单独指定某个线程池:@Async("taskExecutor")
@Service
public class AsyncService {
@Async("taskExecutor")
public void asyncMethod() {
// 这里将会使用注入的taskExecutor线程池执行异步方法
}
}
也可以全局配置,比如在启动类@EnableAsync注解中指定默认的线程池Bean名称
@SpringBootApplication
@EnableAsync("taskExecutor")
public class MyApp {
}
@Service
public class AsyncService {
// 所有异步方法都会去taskExecutor线程池执行
@Async
public void asyncMethod1() {
}
@Async
public void asyncMethod2() {
}
}
异步方法返回类型问题:
如果异步方法的返回类型不是void,调用者得到的将是代表异步操作的Future,而不是操作的实际结果。
@Async
public Future<String> asyncMethod() {}
目录