zoukankan      html  css  js  c++  java
  • springboot:嵌套使用异步注解@Async还会异步执行吗

    一、引言

    在前边的文章《[springboot:使用异步注解@Async的那些坑》中介绍了使用@Async注解获取任务执行结果的错误用法,今天来分享下另外一种常见的错误。

    二、代码演示

    下面是我的controller的代码,

    package com.atssg.controller;
    
    import com.atssg.service.MyAsyncService;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @Slf4j
    @RequestMapping("/sync/")
    @RestController
    public class SyncController2 {
        @Autowired
        private MyAsyncService syncService;
    
        @GetMapping("/test2")
        public String test2() {
            return syncService.syncMethod("hello world");
        }
    }
    
    

    在controller中调用了service层的syncMethod方法,下面看该方法的定义,

    package com.atssg.service;
    
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.Future;
    @Slf4j
    @Service
    public class MyAsyncService {
        @Autowired
        private SyncService syncService;
        public String syncMethod(String str) {
            String result = null;
            try {
                log.info("start,{}",System.currentTimeMillis());
                //调用method4方法,该方法中会桥套调用另外一个异步方法
                Future<String> futureResult = syncService.method4(str);
                result = futureResult.get();
                log.info("end:{}",System.currentTimeMillis());
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
            return result;
        }
    }
    
    

    method4方法是一个异步的方法,在该方法内部会调用另外一个异步的方法,下面看该method4方法的定义,

    /**
         * 调用另一个异步方法
         *
         * @param str
         * @return
         * @throws InterruptedException
         */
        public Future<String> method4(String str) throws InterruptedException {
    
            //method4方法睡眠10s
            Thread.sleep(1000 * 10);
            //调用另外一个异步方法
            method1(str);
            return new AsyncResult<>(str);
        }
    

    下面看method1方法,

    public Future<String> method1(String str) throws InterruptedException {
            Thread.sleep(1000 * 10);
            return new AsyncResult<>(str);
        }
    

    该方法也是睡眠10s。另外这两个方法均是异步方法,有小伙伴会疑惑,怎么没有标注异步注解@Async那,这是因为该注解可以用在方法上也可以用在类上,在前面的文章中说过,不知道小伙伴还记得吗,不清楚的可以再看下给注解的定义哦。下面是我的类,大体看下,

    image

    小伙伴们看到了吗,我是在类上标注了@Async的哦,这样对于该类中所有的方法都是起作用的,即所有方法都是异步的。

    按照正常的逻辑来分析,method4和method1都是异步方法,且两个方法均睡眠10s,那么异步执行的结果应该是10s多点,但这里是在method4中调用了method1,即嵌套调用,那么结果会是什么样子那。看下执行结果,

    image

    看到这个执行结果小伙伴是不是很惊讶,执行时间大约是20s多点,不相信的小伙伴可以多执行几次,结果发现都是20s多点,这是为什么,不应该是10s多点,难道异步执行失效了吗

    三、总结

    在异步方法中调用另外一个异步方法会导致异步执行失败,就是上面的执行结果,所以不要在异步方法中再调用异步方法,达到异步执行的目的。有小伙伴会问这是为什么那,事先透露下这个要从异步的原理说起,异步的原理是通过代理实现的,更多内容欢迎关注下集更精彩。

    推荐阅读
    springboot:使用异步注解@Async获取执行结果的坑
    springboot:异步调用@Async

    image

    一个爱写文章的程序员,欢迎关注我的公众号“北漂程序员”。我有故事,你有酒吗
  • 相关阅读:
    nmap扫描工具
    cobbler全自动批量安装部署linux
    使用ngxtop实时监控nginx
    Nginx 错误汇总
    定制sudo的密码保持时间以及如何不需要密码
    解决eclipse中出现Resource is out of sync with the file system问题
    log4j:ERROR Category option " 1 " not a decimal integer.错误解决
    properties文件中中文不能显示或者中文乱码
    Log4j使用总结
    eclipse, Log4j配置(真心的详细~)
  • 原文地址:https://www.cnblogs.com/teach/p/15202284.html
Copyright © 2011-2022 走看看