同步OR异步?WebFlux开发真的比Servlet开发要快?顺便再科普下CompletableFuture
在看下文之前,先给大家科普一点基础知识
Runable:线程任务类接口,没有返回值
Callable:与上面的不同就是有返回值
Executor:定义了线程池执行任务的接口,不过只定义了Runable的,也就是execute
ExecutorService:是线程池的规范,像ThreadPoolExecutor就是它的实现类,继承了Executor,并且自己还扩展了对于Callable任务类的执行规范,也就是submit()
Executors:一个工具类,提供了一些有默认配置的线程池,如new FixedThreadPool(int num),其实除了newWorkStealingPool(使用的是ForkJoinPool)外使用的都是ThreadPoolExecutor,包括ScheduledThreadPoolExecutor,定时器线程池,只是队列使用的是
DelayedWorkQueue这种延时阻塞队列.
Future: java对于future模式实现的接口
FutureTask:Future接口的实现类
首先,请大家思考一个问题,异步与同步是什么?区别在哪里?看清楚,这里说的是异步和同步,而不是阻塞与非阻塞(阻塞与非阻塞的区别是在于线程是否被阻塞的概念,也就是碰到一个会阻塞的代码(如IO)你是开启子线程去运行让主线程直接过还是让主线程去阻塞等着).
相比于阻塞和非阻塞这种定义非常清晰直观的观念,同步与异步的概念则非常模糊,在我刚接触NIO与AIO的时候因为网上各种博客的误导以及自己也没有花时间思考其本质(独立思考很重要,不要只是被动接受),导致一度理解为同步和异步的概念是操作系统级别的,也就是这个任务的触发是系统主动通知你(回调)的,还是你在程序里不停的轮询查看是否达到触发条件的.
其实,这只是表面现象,大家想想,程序主动访问和系统通知你,这两个真正的区别在于什么?其实是在于一个是需要我们不停的轮询,不停的人为查看.而另一个则是通过回调函数,也就是由完成任务的事件触发的,不需要我们去人为观察的.这才是同步和异步的区别,同步在某一个点上仍然需要去主动访问我们的任务线程.而异步,则是任务线程自己告诉我们,我们已经完成了.也就是说,它们真正的区别在于,有没有完成任务后的回调函数!
理解到了这个,我们再来说说对于CompletableFuture,首先,此类是java第一个真正的异步编程实现,FutureTask则是同步,原因也很简单,你需要主动去拿FutureTask里的返回值(get()方法),也就顺应了我们上文对于同步的观点,同步是需要我们程序去主动访问我们的任务线程
CompletableFuture则不需要我们主动获取,原因也很简单,CompletableFuture是基于事件驱动的数据处理.也就是说,CompletableFuture可以注册监听器,这样一旦我们的数据处理完成就会自动触发回调
下面是一个小的demo
从打印的信息来分析
1.在我们没有指定线程池的情况下CompletableFuture默认使用的是ForkjoinPool,而ForkjoinPoll的线程则是守护线程,这也就是我为什么要在最后join的原因.(守护线程的生存周期是依赖于前台线程的,也就是说,我主线程运行完了jvm就直接退出而不会管守护线程是否还在执行.)
2.虽然在链式的每一个调用里都指定了异步,整个方法链依然使用的是同一个线程,原因是这些调用都存在依赖关系,所以我一直觉得CompletetableFuture的链式调用挺鸡肋的.但是!虽然在链式调用里方法的运行是串行的,但对于外面调用它的线程来说,它依然是异步的(参考上文对与异步的定义)
上面之所以说CompletableFuture的概念,是因为CompletableFuture其实就是典型的响应式编程风格,为我们下面要说的WebFlux做个铺垫,所以我们下面再来说说WebFlux最大的误区,也就是响应式编程相比于Servlet效率更高,性能更好,响应时间更短
大家都知道,Spring5推出了一个WebFlux开发框架,(使用Netty做的默认服务器,并且不使用Servlet规范),利用Mono(对应单例)和WebFlux(对应多例)
我们看下面这个例子
首先请注意,Mono是Netty提供的实现而非Spring,之后再请大家思考一个过程,当我访问这个代码的时候,会发生什么呢?
Spring会去启动一个线程去处理Mono方法调用链,之后马上返回,看清楚,是启动,都不一定开始运行,可能只是就绪的状态就会返回(这里科普下线程生命周期的一个基础知识,当你启动一个线程后,此线程并非会马上运行,它还需要等待cpu的时间片)
但是!这里马上会返回的意思是处理Request请求的线程马上返回,而Response线程则不会马上响应给客户端,因为Mono线程还需要处理数据呢,而当Mono线程处理数据之后,会通过事件的形式被Response监听到,此时Response拿到数据后返回(此处可以理解为Mono在处理完数据后push给了Response)
Ok,这里大家应该都懂了吧,WebFlux框架在我们程序看来是异步的,但是在客户端响应看来还是同步的(因为我还是需要你返回给我数据我才可以响应给客户端),
也正因此,在WebFlux和传统Servlet开发都可以使用多线程的情况下WebFlux框架完全没有比之前Request和Response同步处理快的点,甚至可能会更慢,因为在开启了大量线程的情况下,线程上下文切换是一个很大的开销.要知道,WebFlux开发始终比传统开发要多开一个线程.
而且最搞笑的一点是,Spring WebFlux框架的这种做法和Servlet 3(异步处理任务,Request即时返回)殊途同归.所以WebFlux框架比Servlet效率更高,响应更快这种说法不攻自破。
所以结论就是,webflux框架真的只是一种编程风格框架,就跟java8提供的函数式编程框架Stream一样,只能降低而不能提高任何性能,webflux框架能实现的,用其它方式一样能做到。
同步OR异步?WebFlux开发真的比Servlet开发要快?顺便再科普下CompletableFuture的更多相关文章
- 初学 Java Web 开发,从 Servlet 开发
1. 基本要求:Java 编程基础 有良好的 Java 语言编程基础,这是必须的,在讨论 Web 开发技术时提了一个 Java 编程基础的问题会被鄙视的. 2. 环境准备 (Eclipse + Tom ...
- day05 Servlet 开发和 ServletConfig 与 ServletContext 对象
day05 Servlet 开发和 ServletConfig 与 ServletContext 对象 1. Servlet 开发入门 - hello world 2. Servlet 的调用过程和生 ...
- Java Servlet开发的轻量级MVC框架最佳实践
在Servlet开发的工程实践中,为了减少过多的业务Servlet编写,会采用构建公共Servlet的方式,通过反射来搭建轻量级的MVC框架,从而加快应用开发. 关于Servlet开发的基础知识,请看 ...
- python 37 同步、异步调用
目录 1. 阻塞与非阻塞 2. 同步与异步 2.1 异步调用 2.2 同步调用 2.3 异步调用回收的第一种方式 3. 异步调用+回调函数 3.1 requests模块 3.2 异步调用回收的第二种方 ...
- Java的同步和异步
同步:发送一个请求,等待返回,然后再发送下一个请求 异步:发送一个请求,不等待返回,随时可以再发送下一个请求 同步可以避免出现死锁,读脏数据的发生,一般共享某一资源的时候用,如果每个人都有修改权限,同 ...
- Nodejs同步和异步编程
同步API:只有当前API执行完成后,才能继续执行下一个API:异步API:当前API的执行不会阻塞后续代码的执行. 同步异步代码执行顺序 同步:从上到下依次执行,前面代码会阻塞后面代码的执行.异步: ...
- 浅谈Excel开发:一 Excel 开发概述
做Office相关的开发工作快一年多了,在这一年多里,在插件的开发中遇到了各种各样的问题和困难,还好同事们都很厉害,在和他们的交流讨论中学到了很多的知识.目前Office相关的开发资料是比较少 ...
- 【转载】浅谈Excel开发:一 Excel 开发概述
博客园就是好,想要什么都给总结了,多谢 原文转载:http://www.cnblogs.com/yangecnu/p/Excel-Develpment-Introduction.html 做Offic ...
- 关于Web开发里并发、同步、异步以及事件驱动编程的相关技术
一.开篇语 我的上篇文章<关于如何提供Web服务端并发效率的异步编程技术>又成为了博客园里“编辑推荐”的文章,这是对我写博客很大的鼓励,也许是被推荐的原因很多童鞋在这篇文章里发表了评论,有 ...
随机推荐
- C#中Json的简单处理
命名空间:Windows.Data.Json在Windows Runtime中,可以使用Json类对获取的Json字符串进行操作,相比DataContractJsonSerializer类操作更加直观 ...
- 在CentOS上把Git从1.7.1升级到1.7.12.4
在CentOS上把Git从1.7.1升级到1.7.12.4 摘要:本文记录了在CentOS 6.3上,把Git从1.7.1升级到1.7.12.4的过程. 1. 概述 在我做的一个项目中,最近我对生产服 ...
- Fire Air(华科校赛 网络赛)
题目 原题链接:https://www.nowcoder.com/acm/contest/106/L 在100000 * 10000的空地上,有n个时间点,每个时间点会在(xi,yi)上种一棵树. 定 ...
- 在Vue中遇到的各种坑 及性能提升
Vue: (1) 没有再模板里引用data数据,会不会引起update.beforeUpdate生命周期函数的执行? 不会 (2)组件改成异步 (3)v-once (4)如果不用template ...
- node节点的部署
master点赋予用户权限 [root@mast-1 k8s]# kubectl create clusterrolebinding kubelet-bootstrap \ > --cluste ...
- 课外作业(建立double类型的小数,按照四舍五入保留2位小数)
举例:
- JavaSE-25 AWT
学习要点 关于AWT AWT容器 布局管理器 AWT组件 事件处理 关于AWT java.awt包与子包 AWT软件包 说明 import java.awt.*; 基本组件使用工具 import ...
- 502 bad gateway nginx
此方法可能仅对于我的问题有效 我在VMware虚拟机启动docker container nginx的,一开始启动nginx的contatiner,在浏览器是可以正常访问的,但次日重新访问时就报502 ...
- [题解] cogs 2240 架设电话线路
http://cogs.pro:8080/cogs/problem/problem.php?pid=2240 与洛谷P2885几乎一致,https://www.luogu.org/problemnew ...
- [模板] Miller-Rabin 素数测试
细节挺多的.. #include<iostream> #include<cstdlib> #include<cstdio> #include<ctime> ...