【响应式编程又变天了?看JDK21虚拟线程如何颠覆!】命令式风格编程一直深受开发者喜爱,如 if-then-else、while 循环、函数和代码块等结构使代码易理解、调试,异常易追踪 。然而 , 像所有好的东西一样,通常也有问题 。这种编程风格导致线程被阻塞时间远超过必要时间 。
1 同步阻塞设计1.1 同步阻塞设计的线程图为了便于你理解,让我们看一个典型的企业用例请求:
- 从DB获取数据
- 从 Web 服务获取数据
- 合并结果并将最终合并的结果发送回用户
如下图,将执行线程从上到下表示为一个垂直箭头:
- 绿色是执行的 CPU 部分
- 红色是线程等待数据的时间
文章插图
图片
1.2 评估JAVA 中 , 平台线程是昂贵资源 , 因为默认 , 每个平台线程消耗 1MB 栈内存 。即 JVM 中运行的平台线程数量有上限 。因此,若一个平台线程专用于用户请求,对高并发用户的应用程序,就带来问题 。传统解决方案是创建一个具有最大线程数的线程池,并根据需要水平或垂直扩展应用程序:
- 垂直扩展意味着向容器或 VM 添加更多资源
- 水平扩展则意味着添加应用程序的更多实例
文章插图
图片
用户请求线程启动两个线程:
- 一个用于处理从数据库获取数据
- 另一个用于从 Web 服务获取数据
- 然后,它将阻塞以获取两者结果,然后继续合并并将数据发送给用户
2.2 评估这将提高性能,因为两个数据获取是并行执行的 。但是 , 即使在大多数时间内可能会有性能提升,但是在短时间内 , 平台线程的数量现在从 1 增加到 3 。从可扩展性看,在那段时间内情况更坏 。
3 响应式样式设计响应式编程设计就是为解决这问题 。
3.1 部分响应式设计线程图在于昂贵的平台线程在阻塞操作期间浪费大部分时间 。随 Servlet 3.0 和 3.1 引入,Servlet 线程在发送 HTTP 数据回用户时无需保持活动状态,这为更巧妙编程打开解决线程阻塞的大门 。Java 8 CompletableFuture类可在其中创建响应式管道 。这种开发风格思想是为该用例指定一个执行管道,而非执行用例本身 。
用户请求线程只需指定用例的 CompletableFuture 管道(或任何其他管道),并在尽可能短的时间内将其释放回线程池(因为无需再保持活动状态以向用户发送数据) 。
文章插图
图片
此时,用户请求线程创建一个运行 3 个活动的管道:
- 先并行运行 FetchDataFromService、FetchDataFromDB
- 再运行 Send2User
评估但这只是部分解决问题,因为从 Web 服务、DB获取数据的实际活动仍是在它们各自的平台线程中阻塞 。这带来问题:SE须确保他从管道中生成的任务不是阻塞的 。这很难做到,因为它是手动完成的,并且肯定是错误的,因为在编译时或运行时它不会被标记为警告或错误 。
推荐阅读
- 如何在实战中使用泛型编程?
- 什么是种子贮藏营养物质的组织形式 什么是种子贮藏营养物质的组织
- 家用挂机式空调安装注意事项 家用挂式空调安装流程
- 周海媚死因正式公布!死于突发性心脏病,4亿财产将由母亲继承
- 2024年,五个Java开发者应该关注的编程趋势
- 创建一个双模式跨运行时的 JavaScript 包,你学会了吗
- Python打造可视化进度条
- Java新的结构化并行模式入门指南
- 看完后,你再也不用怕面试问并发编程啦
- 通过网站微调的方式可稳定关键词排名