配置异步

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;

都会以方法为维度,在map中维护方法和线程池的映射关系
private final Map<Method, AsyncTaskExecutor> executors = new ConcurrentHashMap(16);


注意事项

l  使用@Async会对@Transactional注解失效,如何生效: B方法上面使用了@Async注解,B中调用了CDC/D分别使用@Transactional做了标注,则可实现事务控制的目的。

l  由于注解是通过代理实现的,调用异步方法的、异步方法不在同一个类上,因为需要托管给IOC容器,才能找到代理类。

l  静态方法上的@Async失效

@Async注解的方法会在一个单独的线程内运行,不会被全局异常处理器捕获,需要自己设置异常处理。