• 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.异步请求是通过容器线程和程序线程的分配来提高效率。

  • 相关阅读:
    Go语言 0 前言
    SVM支持向量机的基本原理
    支持向量机通俗介绍
    线程句柄和线程ID的区别
    分布式事务一致性,事务补偿实战
    ResultSet is from UPDATE. No Data.
    linux 批量kill进程
    mysql数据表拷贝
    Maven assembly 打包
    JS 删除对象属性
  • 原文地址:https://www.cnblogs.com/shadoll/p/14447854.html
Copyright © 2020-2023  润新知