配置异步
1、使用默认线程池
- 在springbootApplication启动类添加@EnableAsync注解
- 在对应方法上添加@Async即可
2、使用自定义线程池
- 在配置线程池的config类上添加@EnableAsync注解、@Configuration(value = "threadPool")
- 在对应方法上添加@Async(value = "threadPool")在value属性上添加对应线程池的名称
注意
@Transactional和@Async注解的实现都是基于spring的AOP,AOP的实现基于动态代理模式。所以需要添加@Configuration注解将其交给springIOC容器管理
深入探讨
被@Async注解修饰的方法,返回值只能是void或者future
- 因为底层线程池只支持这两种类型的返回,executor.submit(task) =====> return new Future<>();executor.execute(task) =====> void
- 需要有返回值的时候、需要用AsyncResult对象包装一下
@Async public Future<String> asyncSay(){ *** return new AsyncResult<>("hshuo"); } //调用 Future<String> future = this.asyncSay(); future.get();
源码
类型不是future、不做处理直接扔掉返回null
if(result instanceof Future){ return ((Future<?>)result).get(); } return null;
private final Map<Method, AsyncTaskExecutor> executors = new ConcurrentHashMap(16);
注意事项
l 使用@Async会对@Transactional注解失效,如何生效: B方法上面使用了@Async注解,B中调用了C、D,C/D分别使用@Transactional做了标注,则可实现事务控制的目的。
l 由于注解是通过代理实现的,调用异步方法的、异步方法不在同一个类上,因为需要托管给IOC容器,才能找到代理类。
l 静态方法上的@Async失效
l @Async注解的方法会在一个单独的线程内运行,不会被全局异常处理器捕获,需要自己设置异常处理。