一、什么是异步
- 异步调用指的是只是发送的调用的指令,调用者无需等待被调用方法完全执行完毕。指令发出后则继续执行下面的流程。
二、异步的使用场景
- 用户抽奖时中奖的奖品会异步发放
三、@Async介绍
- 在Spring中,基于@Async标注的方法,称之为异步方法;这些方法将在执行的时候,将会在独立的线程中被执行,调用者无需等待它的完成,即可继续其他的操作。
- 首先在启动类上加上 @EnableAsync 注解
- 在需要异步的方法上加上 @Async 注解,表示此方法是一个异步方法
- @Async也可使用自定义线程池
- @Async("自定义线程池bean name")
四、@Async实现异步
1. 在SpringBoot启动类上添加开启异步注解
@EnableAsync -> 异步注解
@SpringBootApplication
public class DrawApplication {
public static void main(String[] args) {
SpringApplication.run(DrawApplication.class, args);
}
}
2. 在要实现异步的方法上添加注解
- 不使用自定义线程池实现
@Async
public void add(int num1 , int num2) {
...要执行代码
}
- 使用自定义线程池实现,需要写一个自定义线程池配置类
@Async("asyncExecutor")
public void add(int num1 , int num2) {
...要执行代码
}
- 自定义线程池配置类
@Configuration public class AsyncConfig { private static final int MAX_POOL_SIZE = 50;//最大线程数 public static final int CORE_POOL_SIZE = 20;//核心线程数 @Bean("asyncExecutor") public AsyncTaskExecutor asyncTaskExecutor() { ThreadPoolTaskExecutor async = new ThreadPoolTaskExecutor(); async.setMaxPoolSize(MAX_POOL_SIZE); async.setCorePoolSize(CORE_POOL_SIZE); async.setThreadNamePrefix("async-thread");//线程名称 async.setWaitForTasksToCompleteOnShutdown(false); async.setQueueCapacity(100);//队列容量 //1. 当任务添加到线程池中被拒绝时,它将抛出 RejectedExecutionException 异常 async.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());//拒绝策略 //2. 当任务添加到线程池中被拒绝时,会在线程池当前正在运行的Thread线程池中处理被拒绝的任务 //async.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); //3. 当任务添加到线程池中被拒绝时,线程池会放弃等待队列中最旧的未处理任务,然后将被拒绝的任务添加到等待队列中。 //async.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy()); //4. 当任务添加到线程池中被拒绝时,线程池将丢弃被拒绝的任务。 //async.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy()); return async; } }
此时再调用此方法可实现异步调用了。
五、注意事项
如下方式会使@Async失效
- 异步方法使用static修饰
- 异步类没有使用@Component注解(或其他注解)导致spring无法扫描到异步类
- 异步方法不能与被调用的异步方法在同一个类中,因为无法产生切面
- 类中需要使用@Autowired或@Resource等注解自动注入,不能自己手动new对象
- 如果使用SpringBoot框架必须在启动类中增加@EnableAsync注解