SpringBoot极简教程 · Spring Boot

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

2020-04-29  本文已影响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秒,所以多个异步调用,总时延是多个异步调用时延的最大值

上一篇 下一篇

猜你喜欢

热点阅读