先看一个简单的示例:

 @RequestMapping("/getFuture")
public Future<String> getFuture() {
System.out.println(1);
// 必须是ListenableFuture的子类,或者CompletionStage子类,或者是DeferredResult 不能是FutureTask
// 如何返回CompletableFuture
CompletableFuture<String> ftu2 = CompletableFuture.supplyAsync(() -> {
try {
// RequestContextHolder.setRequestAttributes(attributes);
// 使用ThreadLocal相关特性时,需要在外面先get
Thread.sleep(3000L);
} catch (InterruptedException e) {
} finally {
// RequestContextHolder.resetRequestAttributes();
}
return "THIS string";
}, es); //Future<String> future = executorService.submit(() -> { }); //返回值是FutureTask return ftu2;
}


客户端发起请求
===> DispatcherServlet根据返回值类型查找对应的handlar AsyncHandlerMethodReturnValueHandler
【Callable -->
CallableMethodReturnValueHandler; DeferredResult,CallableFuture,ListenableFuture --> DeferredResultMethodReturnValueHandler】
===> Controller中返回Future对象给容器, 
org.springframework.web.context.request.async.WebAsyncManager#startDeferredResultProcessing处理Future结果的监听 ===>
sleep3秒之后,Future完成后调用asyncWebRequest.dispatch() 重新发给Container,DispatcherServlet找到Message的序列化器将结果输出。DispatcherServlet.doService会进入两次!!!
异步线程的主要功能是: 
业务处理耗较长(上面的sleep3)时,可以先返回Future对象释放Container的work线程, work线程可以接收更多的请求。等Future完成之后重新调用Container的另一个work线程,输出response. 这里work线程可以是BIO中work线程, 也可以是NIO中work线程 不是所有的Future都能在异步线程中处理
https://www.cnblogs.com/dennyzhangdd/p/7010972.html spring boot中配置container的work线程数量
server.tomcat.max-threads=5
server.tomcat.min-spare-threads=3
 
使用异步处理的优点:
增加系统吞吐量,对响应速度提高不大,可能还会降低
缺点:
线程关系复杂, 异步超时、异常日志拦截需要实现具体的Adapter接口,threadLocal不好清理 参考:《亿级流量架构核心技术》http://jinnianshilongnian.iteye.com/blog/2245925
Servlet3.1 规范
    tomcat线程配置 https://www.cnblogs.com/kismetv/p/7806063.html
遗留问题: Future.get是什么时候调用的?
没有直接调用get。 ListenerableFuture, CompletableFuture任务完成之后都会触发回调 work1线程: 接收到请求---> DispatcherServlet--> return future -->WebAsyncManager#startDeferredResultProcessing
自定义的任务线程: CompletableFuture.postComplete之后调用 WebAsyncManager#setConcurrentResultAndDispatch
work2线程: dipatch ---> DispatcherServlet --> response.out 关于第二个任务线程
当返回值是Callable时,调用WebAsyncManager#startCallableProcessing, 此时任务线程使用的是AsyncTaskExecutor,
可以通过org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter#configureAsyncSupport设置自定义的AsyncTaskExecutor 当返回值是DeferredResult,ListenableFuture (Spring提供),CompletableFuture(JDK自带)时,调用WebAsyncManager#startDeferredResultProcessing,此时任务线程池可以直接指定
@See CompletableFuture.supply(xxxTask, threadPool)
@RequestMapping("/callableTest")
public Callable<String> callableTest() {
Callable<String> hello = () -> {
// 此处不能设置线程池, WebAsyncManager中会使用AsyncSupportConfigurer的线程池
System.out.println("===>" + Thread.currentThread().getName());
return "HELLO";
};
return hello;
}
												

SpringMVC DeferedResult和servlet3.1 AsyncContext异步请求的更多相关文章

  1. 深入理解Servlet3.0异步请求

    异步请求的基础概念 异步请求最直接的用法就是处理耗时业务,Http协议是单向的,只能客户端拉不能服务器主推. 异步请求的核心原理主要分为两大类:1.轮询.2长连接 轮询:就是定时获取返回结果. 长连接 ...

  2. 15.SpringMVC之异步请求

    SpringMVC中异步请求相关组件 SpringMVC在此基础上对异步请求进行了封装.提供了AsyncWebRequest类型的request,并提供了处理异步请求的管理器WebAsyncManag ...

  3. 天天写同步,5种SpringMvc异步请求了解下!

    引言 说到异步大家肯定首先会先想到同步.我们先来看看什么是同步? 所谓同步,就是发出一个功能调用时,在没有得到结果之前,该调用就不返回或继续执行后续操作. 简单来说,同步就是必须一件一件事做,等前一件 ...

  4. springmvc webservlet 异步请求总结

    1:每次请求会启动一个新线程 上边在debug状态下, 每次请求一次,生成一个新的 thread  在此已经是245了 出现一个现象在debug模式下, 每次请求生成的线程,自动在红框那个位置停了下来 ...

  5. Springmvc中 同步/异步请求参数的传递以及数据的返回

    转载:http://blog.csdn.net/qh_java/article/details/44802287 注意: 这里的返回就是返回到jsp页面 **** controller接收前台数据的方 ...

  6. Filter 快速开始 异步Servlet 异步请求 AsyncContext 异步线程 异步派发 过滤器拦截

    [web.xml] <filter> <filter-name>normalFilter</filter-name> <filter-class>net ...

  7. springmvc中同步/异步请求参数的传递以及数据的返回

    注意: 这里的返回就是返回到jsp页面 **** controller接收前台数据的方式,以及将处理后的model 传向前台***** 1.前台传递数据的接受:传的属性名和javabean的属性相同 ...

  8. 【坑】前端使用ajax异步请求以后,springMvc拦截器跳转页面无效

    文章目录 前言 `$.ajaxSetup( )` 后记 前言 本文着重解决前后端分离开发的页面调整问题. 笔者,在做一个需求,需要对访问网站,但是没有登录的用户进行拦截,将他们重定向到首页. 很简单的 ...

  9. 使用Callable或DeferredResult实现springmvc的异步请求

    使用Callable实现springmvc的异步请求 如果一个请求中的某些操作耗时很长,会一直占用线程.这样的请求多了,可能造成线程池被占满,新请求无法执行的情况.这时,可以考虑使用异步请求,即主线程 ...

随机推荐

  1. POJ 1187 陨石的秘密 (线性DP)

    题意: 公元11380年,一颗巨大的陨石坠落在南极.于是,灾难降临了,地球上出现了一系列反常的现象.当人们焦急万分的时候,一支中国科学家组成的南极考察队赶到了出事地点.经过一番侦察,科学家们发现陨石上 ...

  2. C++中的一类临时对象

    类名(参数名)这样的对象是临时对象,不能取地址,不能被引用,不过可以给同类型的其他对象赋值,该临时对象定以后可以进行一次操作,然后立即销毁. 当我们定义一个对象以后并不想立即给它赋初值,而是以后给它赋 ...

  3. JavaPersistenceWithHibernate第二版笔记-第七章-001Mapping a set(@ElementCollection、@CollectionTable、@JoinColumn、)

    一.结构 二.代码 1. package org.jpwh.model.collections.setofstrings; import org.jpwh.model.Constants; impor ...

  4. ZROI2018提高day6t2

    传送门 分析 将所有字母分别转化为1~26,之后将字符串的空位补全为0,?设为-1,我们设dp[p][c][le][ri]表示考虑le到ri个字符串且从第p位开始考虑,这一位最小填c的方案数,具体转移 ...

  5. python3-file的修改实现类似shell中sed的功能

    # Auther: Aaron Fan '''思路:目的是为了修改yesterday这个文件,但是因为无法直接去修改这个文件,所以需要先把修改好的内容写入高yesterday.new这个文件中,然后再 ...

  6. [转]CentOS 7.3 安装MySQL

    1.下载mysql源 yum -y install wget wget https://dev.mysql.com/get/mysql57-community-release-el7-11.noarc ...

  7. Arcgis android 10.2安装方法

    请仔细对照博文做!!! 将arcgis android 10.2的压缩包解压 arcgis android 10.2下载地址http://pan.baidu.com/s/1sj2LKO9 Help-& ...

  8. PowerDesigner 16.5 链接SQL Server 2008R2

    链接的目的主要是为了使用PowerDesigner反向工程生成数据字典 Step1: 在Workspace中创建New Physical Data Model, 否则不会出现Database菜单 当链 ...

  9. javascript 字典类型的使用

    javascript  字典类型的使用 1.使用Array: var arr = new Array(); arr["zs"] = "zhangsan"; ar ...

  10. PS2018学习笔记(03-18节)

    3-认识主界面 # 主界面包括: 菜单栏.选项栏.工具栏.面板.图像编辑窗口(中间)和状态栏(底部): # 界面设置: 方法1:Ctrl+k:打开界面设置; 方法2:编辑-首选项-界面 # shift ...