通常的,Java中的方法调用都是同步调用,有些时候我们需要异步的去执行一些方法的时候,就可以实现异步方法或者使用消息队列实现异步。
使用@Async标注某方法,可以使该方法变成异步方法,在被调用的时候,将会开启新的线程执行方法,不需等待该方法执行完成即可执行下面的代码。
使用异步方法时,需要注意一下几点
一、启用异步功能
在启动类上添加@EnableAsync注解
@Slf4j
@SpringBootApplication
@ComponentScan(basePackages = {"com.xxx.xxx"})
@EnableAsync// 开启异步调用
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args)
}
}
或者自定义一个执行线程池,在配置的时候启用
@Configuration
@EnableAsync
public class AsyncTaskExecutorConfig {
/** 核心线程数 */
private static final int corePoolSize = 20;
/** 最大线程数 */
private static final int maxPoolSize = 100;
/** 允许线程空闲时间(单位:默认为秒) */
private static final int keepAliveTime = 10;
/** 缓冲队列大小 */
private static final int queueCapacity = 200;
/** 线程池名称前缀 */
private static final String threadNamePrefix = "Async-";
@Bean("taskExecutor")
public ThreadPoolTaskExecutor taskExecutor(){
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setQueueCapacity(queueCapacity);
executor.setKeepAliveSeconds(keepAliveTime);
executor.setThreadNamePrefix(threadNamePrefix);
// CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}
二、创建异步方法类
@Component
public class AsyncTask {
@Async("taskExecutor")//用的是配置的线程池
public void task1() throws InterruptedException {
System.out.println("task1开始");
Thread.sleep(5000);
System.out.println("task1结束");
}
@Async//用的默认的线程池
public void task2() throws InterruptedException {
System.out.println("task2开始");
Thread.sleep(5000);
System.out.println("task2结束");
}
}
三、调用异步方法
public class TaskServic {
@Autowired
private AsyncTask asyncTask;
public void start() throws InterruptedException {
System.out.println("start开始");
asyncTask.task1();
asyncTask.task2();
System.out.println("start结束");
}
}
注意事项:以下情况会使异步方法失效
- 异步方法使用static修饰
- 异步类没有使用@Component注解导致spring无法扫描到异步类
- 异步方法不能与被调用的异步方法在同一个类中
- 类中需要使用@Autowired或@Resource等注解自动注入,不能自己手动new对象
- 在配置中增加@EnableAsync注解