springboot/springcloud中异步注解@Async的使用并且接收返回的结果

一、在启动类添加@EnableAsync

@SpringBootApplication
@EnableAsync
public class AccountApplication {
    public static void main(String[] args) {
        SpringApplication.run(AccountApplication.class,args);
    }
}

二、在方法上添加@Async

@Service
public class  UserService {
    @Async
    public synchronized String getUser() {
        System.out.println(Thread.currentThread().getName()+":*用户服务被调用"+Thread.currentThread().getId());
        return "这里是用户服务端!";
    }
}

三、Controller层

    @Autowired
    private UserService userService;

    @RequestMapping("/u")
    public String userInfo() {
        String user = userService.getUser();
        return user;
    }

四、测试结果

 会发现异步调用没问题,但是,Controller拿不到这个异步方法返回的值,为null,浏览器页面空白,如何能异步调用又能拿到返回值呢?

五、获取结果

异步它离不开线程,得到线程有三种方法,继承Thread和实现Runnable都是没有返回值的,Callable+Future可以得到返回值,Future是干啥的呢?翻源码查看介绍如下:

 * A {@code Future} represents the result of an asynchronous
 * computation.  Methods are provided to check if the computation is
 * complete, to wait for its completion, and to retrieve the result of
 * the computation.  The result can only be retrieved using method
 * {@code get} when the computation has completed, blocking if
 * necessary until it is ready.  Cancellation is performed by the
 * {@code cancel} method.  Additional methods are provided to
 * determine if the task completed normally or was cancelled. Once a
 * computation has completed, the computation cannot be cancelled.
 * If you would like to use a {@code Future} for the sake
 * of cancellability but not provide a usable result, you can
 * declare types of the form {@code Future<?>} and
 * return {@code null} as a result of the underlying task.

大致意思是说Future表示异步的计算结果,它提供了一些方法去检查计算是否完成,并且等待计算完成,然后接收计算的结果,并且计算完成后结果只能用get方法接收到......

  看到这里我们就大致明白它怎么接收返回值的了,怎么样使用到上面异步方法中得到结果呢,直接new?但它是个接口,里面一堆方法得重写,而且并没有提供方法让我们把返回结果放进去,那怎么用呢?可以查看它的实现类(IDEA快捷键:ctrl+alt+b)发现有个ListenableFuture实现了它,但是ListenableFuture也没有提供解决的办法,继续查看ListenableFuture的实现类可以发现AsyncResult实现了它并且自带有构造器,于是乎,把异步方法的返回值放进去返回,并且用Future的get方法在Controller层接收岂不美哉,在这里又想到又是继承又是实现的绕这么大圈,何不自己写个带构造器的类并且实现Future呢,后来想想还是算了,人家都提供好了还自己写,闲得蛋疼,直接用人家提供的AsyncResult类解决,于是乎,上面Service中的异步方法就变成了这样:

@Service
public class  UserService {

    @Async
    //用Future<>类型返回
    public Future<String> getAsycUser() {
        System.out.println(Thread.currentThread().getName()+":异步用户服务被调用2");

        //结果放进带构造器的Future子类AsyncResult返回
        return new AsyncResult<>("这里是异步用户服务端-2!");
    }

}

Controller中用Future提供的get接收:

   @RequestMapping("/asycu")
    public String getAsycUser() throws ExecutionException, InterruptedException {
        //调用异步方法返回类型为Future<>
        Future<String> future = userService.getAsycUser();
        
        //get方法得到返回的结果
        return future.get();
    }

测试结果:

 可以发现成功实现了异步并且得到了返回值,而且里面的线程数由8个增加到了了17个,此接口不光在同一个微服务中适用,在别的微服务中远程调用也同样管用。

posted @ 2022-05-07 14:48  蒂雪凌星  阅读(4102)  评论(0编辑  收藏  举报
Live2D