先看一个简单的示例:

 @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. SNNU女装T台走秀(状压dp)

    呜啦啦啦啦啦啦~~!!SNNU首届女装T走秀大赛开始了! 本次比赛共有N名队员希望参加比赛:ddjing希望这次比赛尽可能的吸睛,因此他决定对N名队员进行一次海选: 多亏ddjing有一双发现美的眼睛 ...

  2. go 语言介绍

    特点1. 静态类型,编译开源语言 2. 脚本化的语法,支持多种编程范式(函数式,面向对象) 3. 原生,给力的并发支持并发编程 Go语言的优势: 1.脚本化的语法:开发效率高,容易上手 2.静态类型+ ...

  3. 利用脚本,一键设置java环境变量(默认安装路径)

    Windows一键设置Java环境变量 右击以管理员方式运行,注意自行更改JAVA_HOME目录文件安装目录. JDKSetting.bat @echo off color 0a echo.----- ...

  4. ROS Learning-022 learning_tf-06(编程) 现在与过去中穿梭 (Python版) --- waitForTransformFull() 函数

    ROS Indigo learning_tf-06 现在与过去中穿梭 (Python版) - waitForTransformFull() 函数 我使用的虚拟机软件:VMware Workstatio ...

  5. Linux网络配置常用命令

    计算机需要网络连接才能和其他计算机通信,这是通过操作系统识别接口卡(如以太网卡.猫等等),并配置该接口以连接到网络上来实现的.网络配置命令可以用来配置以下类型的网络接口:以太网.ISDN(综合业务数字 ...

  6. 使用paramiko连接EC2主机

    在亚马逊云上建的主机没有密码,只有一个PEM文件.所以paramiko需要通过该PEM文件登录云主机进行管理 有两种方式,第一种被我注解了 import paramiko ssh = paramiko ...

  7. 20169219《Linux内核原理及分析》第十二周作业

    格式化字符串漏洞实验 格式化字符串攻击原理是利用格式化函数(如printf())的沿着堆栈指针向下打印的特性,通过只提供格式化字符串但不提供对应的变量,读取栈内空间的内容. 更进一步,通过将某个要攻击 ...

  8. 常用Linux命令:ls/cd/pwd/mkdir/rm/mv/cp

    一.ls:列出目标目录中所有的子目录和文件 1.命令格式 ls [选项] [目录名] 2.常用参数 -a :列出目录下所有文件 -h :以容易理解的格式列出文件大小 -l  :除了文件名之外,还将文件 ...

  9. C# 抽象方法及抽象类 Abstract 及接口

    public abstract class Animal { public abstract void Dosth(); } 该类中只有虚方法  那么我们可以用abstract来修饰  将该类称为抽象 ...

  10. UWP&WP8.1图片照片添加水印

    水印可以自己自己制作,也可以用代码写. 我这里主要写如何添加到照片上面. UWP和WP8.1添加的方法一样.代码是通用的. UWP和WP8.1没有像WPF和WINFROM中darw这样简便的API可以 ...