SpringBoot中异步请求的使用

一.前言

  正常的http请求是由一个线程从头到尾来处理,当如果有请求耗时过长,而我们容器的线程数量是有限的,但所有线程都在使用,就会造成新的请求无法进行。

  异步请求可以实现当http请求进入到程序,可以先释放容器的线程,由程序内部的线程进行处理,等处理完成后,再调回容器的线程来返回请求结果。这就可以在一定程度上提高系统的吞吐量。

二.实现

  1.使用Servlet方法来实现

@RequestMapping(value = "/importData", method = RequestMethod.POST)
public void importData(HttpServletRequest request) {
    AsyncContext asyncContext = request.startAsync();
    //设置监听器:可设置其开始、完成、异常、超时等事件的回调处理
    asyncContext.addListener(new AsyncListener() {
      @Override
        public void onTimeout(AsyncEvent event) throws IOException {
          System.out.println("超时了...");
          //做一些超时后的相关操作...
        }
        @Override
        public void onStartAsync(AsyncEvent event) throws IOException {
          System.out.println("线程开始");
        }
        @Override
        public void onError(AsyncEvent event) throws IOException {
          System.out.println("发生错误:"+event.getThrowable());
        }
        @Override
        public void onComplete(AsyncEvent event) throws IOException {
          System.out.println("执行完成");
          //这里可以做一些清理资源的操作...
        }
    });
    //设置超时时间
    asyncContext.setTimeout(3000000);//5分钟
    asyncContext.start(() -> {
        Result rm = new Result();
        try {
            System.out.println("内部线程:" + Thread.currentThread().getName());
            asyncContext.getResponse().setCharacterEncoding("utf-8");
            asyncContext.getResponse().setContentType("text/html;charset=UTF-8");
            asyncContext.getResponse().getWriter().println("返回成功");
        } catch (Exception e) {
            System.out.println("异常:" + e);
        }
        //异步请求完成通知
        //此时整个请求才完成
        asyncContext.complete();
    });
    //此时之类 request的线程连接已经释放了
    System.out.println("主线程:" + Thread.currentThread().getName());
}

   2.在SpringBoot中可以使用Callable、DeferredResult、WebAysncTask。这里只举Callable的代码例子。

@RequestMapping("/callable")
public Callable<String> callable() {
    log.info("外部线程:" + Thread.currentThread().getName());
    return new Callable<String>() {

        @Override
        public String call() throws Exception {
            log.info("内部线程:" + Thread.currentThread().getName());
            return "callable!";
        }
    };
}

三.总结

  1.异步请求可以有效提供系统的吞吐量。

  2.异步请求是通过容器线程和程序线程的分配来提高效率。

原文地址:https://www.cnblogs.com/shadoll/p/14447854.html