一、@Async注解简介
Spring为任务调度与异步方法执行提供了注解支持。通过在方法上设置@Async注解,可使得方法被异步调用。也就是说调用者会在调用时立即返回,而被调用方法的实际执行是交给Spring的TaskExecutor来完成。
二、配置与使用
我们可以使用springBoot默认的线程池,不过一般我们会自定义线程池(因为比较灵活)
@Configuration
@EnableAsync
public class TaskExecutorConfig {
/**
* 创建异步调用的线程池
* @return
*/
@Bean("taskExecutor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(200);
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix("taskExecutor-");
// 用来设置线程池关闭的时候等待所有任务都完成再继续销毁其他的Bean,这样这些异步任务的销毁就会先于Redis线程池的销毁
executor.setWaitForTasksToCompleteOnShutdown(true);
// 设置线程池中任务的等待时间,如果超过这个时候还没有销毁就强制销毁,以确保应用最后能够被关闭,而不是阻塞住
executor.setAwaitTerminationSeconds(60);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return executor;
}
}
编写异步方法
@Service
public class AsyncTaskService {
@Async("taskExecutor")
public void doTask(){
try {
Thread.sleep(5 * 1000);
System.out.println("睡眠完成");
} catch (Exception e){
System.out.println(e.getMessage());
}
}
}
进行测试
/**
* 修改用户
*
* @return 结果
*/
@GetMapping("/task")
@ResponseBody
public Map<String, Object> task() {
System.out.println("---- 执行前 -------");
asyncTaskService.doTask();
System.out.println("---- 执行后 -------");
Map<String, Object> resultMap = new HashMap<>(16);
resultMap.put("code", 200);
resultMap.put("msg", "执行成功");
return resultMap;
}
异步调用成功
三、注意事项
如下方式会使@Async失效
-
异步方法使用static修饰
-
异步类没有使用@Component注解(或其他注解)导致spring无法扫描到异步类
-
异步方法不能与被调用的异步方法在同一个类中
-
类中需要使用@Autowired或@Resource等注解自动注入,不能自己手动new对象
-
如果使用SpringBoot框架必须在启动类中增加@EnableAsync注解