You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3.1 KiB
3.1 KiB
作用
spring容器中实现bean方法的异步调用。 比如有个logService的bean,logservice中有个log方法用来记录日志,当调用 logService.log(msg)的时候,希望异步执行,那么可以通过 @EnableAsync & @Async 来实现。
用法
- 需要异步执行的方法上面使用 @Async 注解标注,若bean中所有的方法都需要异步执行,可以直接将 @Async 加载类上。
- 将 @EnableAsync 添加在spring配置类上,此时 @Async 注解才会起效。
常见2种用法
- 无返回值的
- 可以获取返回值的
无返回值的
有返回值的
案例
!
!
!
方法之间无关联的可以采用异步的方式,并行去获取,最终耗时为最长的那个方法,整体相对于同步的方式性能提升不少。
自定义异步执行线程池
方式1、在Spring容器中定义一个线程池类型的bean,bean名称必须是taskExecutor
方式二、实现接口AsyncConfigurer
自定义异常处理
异常处理分2种情况
- 当返回值是Future的时候,方法内部有异常的时候,异常会向外抛出,可以对Future.get采用try..catch来捕获异常
!
- 当返回值不是Future的时候,可以自定义一个bean,实现AsyncConfigurer接口中的getAsyncUncaughtExceptionHandler方法,返回自定义的异常处理器
!
线程池隔离
什么是线程池隔离?
一个系统中可能有很多业务,比如充值服务、提现服务或者其他服务,这些服务中都有一些方法需要异 步执行,默认情况下他们会使用同一个线程池去执行,如果有一个业务量比较大,占用了线程池中的大 量线程,此时会导致其他业务的方法无法执行,那么我们可以采用线程隔离的方式,对不同的业务使用不同的线程池,相互隔离,互不影响。@Async 注解有个 value 参数,用来指定线程池的bean名称,方法运行的时候,就会采用指定的线程池来执行目标方法。
使用步骤
- 在Spring容器种,自定义线程池相关的bean
- @Async("线程池bean名称")
例
原理
内部使用aop实现的,@EnableAsync会引入一个bean后置处理器:AsyncAnnotationBeanPostProcessor ,将其注册到spring容器,这个bean后置处理器在所有bean创建过程中,判断bean的类上是否有@Async注解或者类中是否有@Async标注的方法,如果有,会通过aop给这个bean生成代理对象,会在代理对象中添加一个切面org.springframework.scheduling.annotation.AsyncAnnotationAdvisor,这个切面中会引入一个拦截器:AnnotationAsyncExecutionInterceptor,方法异步调用的关键代码就是在这个拦截器的invoke方法中实现的。