美文网首页SpringBoot极简教程 · Spring Boot
异步调用多个@Async方法获得返回值时延的测试

异步调用多个@Async方法获得返回值时延的测试

作者: 千里行者 | 来源:发表于2020-04-29 12:37 被阅读0次

    一般我们在使用@Async注解的时候,其注解的方法是不带返回值的,不过有的时候,某些功能可能需要我们异步调用且获得返回值。

    被@Async注解的方法,返回值类型需要是Future<T>类型,所以需要写一个Future<T>的实现类,用于做异步调用方法的返回。

    public class AsyncResult<V> implements Future<V> {
        private final V value;
    
        public AsyncResult(V value) {
            this.value = value;
        }
    
        public boolean cancel(boolean mayInterruptIfRunning) {
            return false;
        }
    
        public boolean isCancelled() {
            return false;
        }
    
        public boolean isDone() {
            return true;
        }
    
        public V get() {
            return this.value;
        }
    
        public V get(long timeout, TimeUnit unit) {
            return this.value;
        }
    }
    

    假设我们在一个方法里想要异步调用好几个方法,获得它们的返回值然后进行下步操作,那么多个调用的延迟是怎样的的呢?我们写些代码测试一下
    测试使用springboot框架,版本是2.0.0RELEASE
    先写一个service

    @Slf4j
    @Service
    public class TestService {
    
        @Async
        public Future<String> testReturnA(){
            log.info("serviceA: " + Thread.currentThread().getName() + " tid: " + Thread.currentThread().getId());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return new AsyncResult<>("testA");
        }
    
        @Async
        public Future<String> testReturnB(){
            log.info("serviceB: " + Thread.currentThread().getName() + " tid: " + Thread.currentThread().getId());
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return new AsyncResult<>("testB");
        }
    }
    

    再写一个controller,test1和test2分别有不同的异步调用顺序

    @Slf4j
    @RequestMapping
    @RestController
    public class TestController {
    
        @Resource
        TestService testService;
    
        @GetMapping("/test1")
        public String test1() {
            log.info("controller 1: " + Thread.currentThread().getName() + " tid: " + Thread.currentThread().getId());
            Future<String> futureA = testService.testReturnA();
            Future<String> futureB = testService.testReturnB();
            try {
                String a = futureA.get();
                String b = futureB.get();
                log.info("controller1 asyn finishes");
                return a + "-" + b;
    
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                return "error";
            }
        }
    
        @GetMapping("/test2")
        public String test2() {
            log.info("controller2: " + Thread.currentThread().getName() + " tid: " + Thread.currentThread().getId());
            Future<String> futureA = testService.testReturnA();
            Future<String> futureB = testService.testReturnB();
            try {
                String b = futureB.get();
                String a = futureA.get();
                log.info("controller2 asyn finishes");
                return a + "-" + b;
    
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                return "error";
            }
        }
    }
    

    本地启动,浏览器分别调用http://localhost:8080/test1http://localhost:8080/test2,均能成功返回“testA-testB”
    日志打印如下

    2020-04-29 12:18:06.912  INFO 20408 --- [nio-8080-exec-2] c.e.boottest.controller.TestController   : controller 1: http-nio-8080-exec-2 tid: 33
    2020-04-29 12:18:06.926  INFO 20408 --- [         task-1] c.example.boottest.service.TestService   : serviceA: task-1 tid: 52
    2020-04-29 12:18:06.926  INFO 20408 --- [         task-2] c.example.boottest.service.TestService   : serviceB: task-2 tid: 53
    2020-04-29 12:18:11.926  INFO 20408 --- [nio-8080-exec-2] c.e.boottest.controller.TestController   : controller1 asyn finishes
    
    2020-04-29 12:18:23.395  INFO 20408 --- [nio-8080-exec-1] c.e.boottest.controller.TestController   : controller2: http-nio-8080-exec-1 tid: 32
    2020-04-29 12:18:23.396  INFO 20408 --- [         task-3] c.example.boottest.service.TestService   : serviceA: task-3 tid: 54
    2020-04-29 12:18:23.397  INFO 20408 --- [         task-4] c.example.boottest.service.TestService   : serviceB: task-4 tid: 55
    2020-04-29 12:18:28.398  INFO 20408 --- [nio-8080-exec-1] c.e.boottest.controller.TestController   : controller2 asyn finishes
    

    可以发现时延迟都是5秒,所以多个异步调用,总时延是多个异步调用时延的最大值

    相关文章

      网友评论

        本文标题:异步调用多个@Async方法获得返回值时延的测试

        本文链接:https://www.haomeiwen.com/subject/ttjgwhtx.html