@Async注解失效可能产生的原因及解决方案

2022-07-15 10:37:15

1.@Async注解失效可能产生的原因及解决方案

1.1.未开启异步配置

需要在SpringBoot启动类上添加@EnableAsync注解

@SpringBootApplication@EnableAsync//开启异步线程配置publicclassAsyncDemoApplication{publicstaticvoidmain(String[] args){
        SpringApplication.run(AsyncDemoApplication.class, args);}}

或者在异步线程池配置类中添加@EnableAsync

@Slf4j@EnableAsync@ConfigurationpublicclassAsyncExecutorConfigimplementsAsyncConfigurer{@Value("${spring.async-executors.core-size}")private String CORE_SIZE;@Value("${spring.async-executors.max-size}")private String MAX_SIZE;@Value("${spring.async-executors.queue-size}")private String QUEUE_SIZE;@Overridepublic ExecutorgetAsyncExecutor(){
        ThreadPoolTaskExecutor executor=newThreadPoolTaskExecutor();
        executor.setCorePoolSize(Integer.parseInt(CORE_SIZE));
        executor.setMaxPoolSize(Integer.parseInt(MAX_SIZE));
        executor.setQueueCapacity(Integer.parseInt(QUEUE_SIZE));
        executor.setThreadNamePrefix("Spring Async Executor-");
        executor.setRejectedExecutionHandler((runnable, threadPoolExecutor)->{try{
                        threadPoolExecutor.getQueue().put(runnable);}catch(InterruptedException e){
                        log.info("Thread pool receives InterruptedException: "+ e);}});
        executor.initialize();return executor;}}
server:port:9081spring:async-executors:core-size:100max-size:200queue-size:500

1.2.异步方法和调用者方法在同一个内中

前置条件开启了异步注解:

例如:

@Slf4j@SpringBootTestclassAsyncDemoApplicationTests{@TestvoidcontextLoads(){for(int i=0; i<10; i++){testMethod(i);}}@AsyncpublicvoidtestMethod(Integer integer){
        log.info("传入的参数为:"+integer);}}

运行测试方法后输出的结果:

2021-05-1115:42:40.544  INFO16020---[           main] com.tangling.AsyncDemoApplicationTests: 传入的参数为:02021-05-1115:42:40.544  INFO16020---[           main] com.tangling.AsyncDemoApplicationTests: 传入的参数为:12021-05-1115:42:40.544  INFO16020---[           main] com.tangling.AsyncDemoApplicationTests: 传入的参数为:22021-05-1115:42:40.544  INFO16020---[           main] com.tangling.AsyncDemoApplicationTests: 传入的参数为:32021-05-1115:42:40.544  INFO16020---[           main] com.tangling.AsyncDemoApplicationTests: 传入的参数为:42021-05-1115:42:40.544  INFO16020---[           main] com.tangling.AsyncDemoApplicationTests: 传入的参数为:52021-05-1115:42:40.544  INFO16020---[           main] com.tangling.AsyncDemoApplicationTests: 传入的参数为:62021-05-1115:42:40.545  INFO16020---[           main] com.tangling.AsyncDemoApplicationTests: 传入的参数为:72021-05-1115:42:40.545  INFO16020---[           main] com.tangling.AsyncDemoApplicationTests: 传入的参数为:82021-05-1115:42:40.545  INFO16020---[           main] com.tangling.AsyncDemoApplicationTests: 传入的参数为:9

从输出结果就可以看出来异步注解没有生效,如果异步注解生效的话他输入的数字应该是乱序的。

1.3.为什么异步方法与调用者在同一个内中会失效

描述内容参考文章

原因是:spring 在扫描bean的时候会扫描方法上是否包含@Async注解,如果包含,spring会为这个bean动态地生成一个子类(即代理类,proxy),代理类是继承原来那个bean的。此时,当这个有注解的方法被调用的时候,实际上是由代理类来调用的,代理类在调用时增加异步作用。然而,如果这个有注解的方法是被同一个类中的其他方法调用的,那么该方法的调用并没有通过代理类,而是直接通过原来的那个bean,所以就没有增加异步作用,我们看到的现象就是@Async注解无效。

1.4.解决办法

将异步方法按照业务统一抽取到对应的bean中,当外部需要使用时将该bean注入,然后调用bean中的异步方法

上述代码改写

异步方法工具类

@Slf4j@ComponentpublicclassAsyncUtils{@AsyncpublicvoidtestMethod(Integer integer){
        log.info("传入的参数为:"+integer);}}

测试类

@Slf4j@SpringBootTestclassAsyncDemoApplicationTests{@Autowiredprivate AsyncUtils asyncUtils;@TestvoidcontextLoads(){for(int i=0; i<10; i++){
            asyncUtils.testMethod(i);}}}

运行输出结果

2021-05-1115:56:11.624  INFO18424---[sync Executor-1] com.tangling.utils.AsyncUtils: 传入的参数为:02021-05-1115:56:11.624  INFO18424---[ync Executor-10] com.tangling.utils.AsyncUtils: 传入的参数为:92021-05-1115:56:11.624  INFO18424---[sync Executor-8] com.tangling.utils.AsyncUtils: 传入的参数为:72021-05-1115:56:11.624  INFO18424---[sync Executor-9] com.tangling.utils.AsyncUtils: 传入的参数为:82021-05-1115:56:11.624  INFO18424---[sync Executor-6] com.tangling.utils.AsyncUtils: 传入的参数为:52021-05-1115:56:11.624  INFO18424---[sync Executor-5] com.tangling.utils.AsyncUtils: 传入的参数为:42021-05-1115:56:11.625  INFO18424---[sync Executor-3] com.tangling.utils.AsyncUtils: 传入的参数为:22021-05-1115:56:11.625  INFO18424---[sync Executor-2] com.tangling.utils.AsyncUtils: 传入的参数为:12021-05-1115:56:11.624  INFO18424---[sync Executor-4] com.tangling.utils.AsyncUtils: 传入的参数为:32021-05-1115:56:11.624  INFO18424---[sync Executor-7] com.tangling.utils.AsyncUtils: 传入的参数为:6
  • 作者:Tang.Mr
  • 原文链接:https://blog.csdn.net/ScholarTang/article/details/116658689
    更新时间:2022-07-15 10:37:15