java-8组合式异步编程

11.1 Future 接口
Future接口在Java5中被引人,设计初衷是对将来某个时刻会发生的结果进行建模。它建模了一种异步计算,返回一个执行运算结果的引用,当运算结束后,这个引用被返回给调用方。在Future中触发那些潜在耗时的操作把调用线程解放出来,让它能继续执行其他有价值的工作,不再需要呆呆等待耗时的操作完成。打个比方,你可以把它想象成这样的场景:你拿了一袋子衣服到你中意的干洗店去洗。干洗店的员工会给你张发票,告诉你什么时候你的衣服会洗好(这就是一个Future事件)。衣服干洗的同时,你可以去做其他的事情。Future的另一个优点是它比更底层的+hread更易用。要使用Future,通常你只需要将耗时的操作封装在一个callable对象中,再将它提交给Executorservice,就万事大吉了。下面这段代码展示了Java8之前使用Future的一个例子。

正像图11-3介绍的那样,这种编程方式让你的线程可以在Executorservice以并发方式调用另一个线程执行耗时操作的同时,去执行一些其他的任务。接着,如果你已经运行到没有异步操作的结果就无法继续任何有意义的工作时,可以调用它的get方法去获取操作的结果。如果操作已经完成,该方法会立刻返回操作的结果,否则它会阻塞你的线程,直到操作完成,返回相应的结果。
你能想象这种场景存在怎样的问题吗?如果该长时间运行的操作永远不返回了会怎样?为了处理这种可能性,虽然Future提供了一个无需任何参数的get方法,我们还是推荐大家使用重载版本的get方法,它接受一个超时的参数,通过它,你可以定义你的线程等待Future结果的最长时间,而不是像代码清单11-1中那样永无止境地等待下去。

11.1.1 Future 接口的局限性
通过第一个例子,我们知道Future接口提供了方法来检测异步计算是否已经结束(使用ispone方法),等待异步操作结束,以及获取计算的结果。但是这些特性还不足以让你编写简洁的并发代码。比如,我们很难表述Future结果之间的依赖性;从文字描述上这很简单,“当长时间计算任务完成时,请将该计算的结果通知到另一个长时间运行的计算任务,这两个计算任务都完成后,将计算的结果与另一个查询操作结果合并”。但是,使用Future中提供的方法完成这样的操作又是另外一回事。这也是我们需要更具描述能力的特性的原因,比如下面这些。
口将两个异步计算合并为一个--这两个异步计算之间相互独立,同时第二个又依赖于第一个的结果。
口等待Future集合中的所有任务都完成
口仅等待Future集合中最快结束的任务完成(有可能因为它们试图通过不同的方式计算同一个值),并返回它的结果。
口通过编程方式完成一个Future任务的执行(即以手工设定异步操作结果的方式)。口应对Future的完成事件(即当Future的完成事件发生时会收到通知,并能使用Future计算的结果进行下一步的操作,不只是简单地阻塞等待操作的结果)。这一章中,你会了解新的completableFuture类(它实现了Future接口)如何利用Java8的新特性以更直观的方式将上述需求都变为可能。stream和completableFuture的设计都遵循了类似的模式:它们都使用了Lambda表达式以及流水线的思想。从这个角度,你可以说CompletableFuture和Future的关系就跟stream和collection的关系一样。
11.1.2 使用 Completableruture 构建异步应用
为了展示completableFuture的强大特性,我们会创建一个名为“最佳价格查询器(best-price-finder)的应用,它会查询多个在线商店,依据给定的产品或服务找出最低的价格。这

个过程中,你会学到几个重要的技能。
口首先,你会学到如何为你的客户提供异步API(如果你拥有一间在线商店的话,这是非常有帮助的)。
口其次,你会掌握如何让你使用了同步API的代码变为非阻塞代码。你会了解如何使用流水线将两个接续的异步操作合并为一个异步计算操作。这种情况肯定会出现,比如,在线商店返回了你想要购买商品的原始价格,并附带着一个折扣代码--最终,要计算出该商品的实际价格,你不得不访问第二个远程折扣服务,查询该折扣代码对应的折扣比率。口你还会学到如何以响应式的方式处理异步操作的完成事件,以及随着各个商店返回它的商品价格,最佳价格查询器如何持续地更新每种商品的最佳推荐,而不是等待所有的商店都返回他们各自的价格(这种方式存在着一定的风险,一旦某家商店的服务中断,用户可能遭遇白屏)。
同步API与异步API
同步API其实只是对传统方法调用的另一种称呼:你调用了某个方法,调用方在被调用方运行的过程中会等待,被调用方运行结束返回,调用方取得被调用方的返回值并继续运行。即使调用方和被调用方在不同的线程中运行,调用方还是需要等待被调用方结束运行,这就是阻寨式调用这个名词的由来。
与此相反,异步API会直接返回,或者至少在被调用方计算完成之前,将它剩余的计算任务交给另一个线程去做,该线程和调用方是异步的--这就是非阻寒式调用的由来。执行剩余计算任务的线程会将它的计算结果返回给调用方。返回的方式要么是通过回调函数,要么是由调用方再次执行一个“等待,直到计算完成”的方法调用。这种方式的计算在IO系统程序设计中非常常见:你发起了一次磁盘访问,这次访问和你的其他计算操作是异步的,你完成其他的任务时,磁盘块的数据可能还没载入到内存,你只需要等待数据的载入完成。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/389944.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java微服务学习Day2

文章目录 Nacos配置管理统一配置管理配置热更新![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/c8a2d17baeef411980b44b432eb9692a.png)配置共享搭建Nacos集群 Feign远程调用介绍自定义配置性能优化最佳实践 Gateway服务网关介绍搭建网关服务路由断言工厂路由过滤器…

【c++】析构函数

1.特征 析构函数是特殊的成员函数,其特征如下: 1.析构函数名是在类名前加上字符~。 2.无参数无返回值类型。 3.一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载。 4.对象生命周…

那些杠鸿蒙的现在怎么样了?

别杠,要杠就是你对。 一个纯血鸿蒙就已经打了那些杠精的嘴,以前是套壳Android,大家纷纷喷鸿蒙。现在鸿蒙已经全栈自研,并且已经展开各大企业生态合作。不管什么独立系统,都是一定要走一遍套壳Android的道路的&#xf…

Spring AMQP(3.1.1)设置ConfirmCallback和ReturnsCallback

文章目录 一、起因二、代码1. 定义exchange和queue2. RabbitTemplate3. EnhancedCorrelationData4. 发送消息 环境如下 VersionSpringBoot3.2.1spring-amqp3.1.1RabbitMq3-management 一、起因 老版本的spring-amqp在CorrelationData上设置ConfirmCallback。但是今天却突然发…

《Go 简易速速上手小册》第1章:Go 语言基础(2024 最新版)

文章目录 1.1 Go 语言的安装与环境配置1.1.1 基础知识讲解案例 Demo:简单的 Go 程序 1.1.2 重点案例:搭建一个 Go Web 服务准备工作步骤 1:创建项目目录步骤 2:编写 Web 服务代码步骤 3:运行你的 Web 服务步骤 4&#…

为什么电路要设计得这么复杂?

首先提出这个问题就很不容易啊,我们看两个精彩回答。 From 骄建: 假设我们回到第一个实用放大电路诞生之前: 某天你开始做一个CS单管放大器,电阻负载,可是有一大堆问题,电阻做的不准,温度对器…

Kotlin基本语法 3 类

1.定义类 package classStudyclass Player {var name:String "jack"get() field.capitalize()set(value) {field value.trim()} }fun main() {val player Player()println(player.name)player.name " asdas "println(player.name)} 2.计算属性与防范…

jmeter遇到连接数据库的问题

jmeter连接mysql或者oracle简单,但是连接过inceptor吗? 上货 1、下载驱动inceptor 5.1.2.jar包 2、在添加驱动那里导入 3、在JBC request中的写法 PS:没什么可说的

【数据结构】10 广义表与多重链表

广义表 广义表不仅跟线性表一样可以表示简单是线性顺序关系,而且可以表达更复杂的非线性多元关系。 G L i s t ( a 1 , a 2 , . . . , a i − 1 , a i , a i 1 , . . . , a n ) GList (a_1, a_2,...,a_{i-1},a_i,a_{i1},...,a_n) GList(a1​,a2​,...,ai−1​,…

【机器学习笔记】7 KNN算法

距离度量 欧氏距离(Euclidean distance) 欧几里得度量(Euclidean Metric)(也称欧氏距离)是一个通常采用的距离定义,指在𝑚维空间中两个点之间的真实距离,或者向量的自然长度(即该点…

分布式文件系统 SpringBoot+FastDFS+Vue.js【四】

分布式文件系统 SpringBootFastDFSVue.js【四】 八、文件的下载和删除功能8.1.FastDFSClient.java8.2.FileServerController.java8.3.Vue的fast.js8.4.fastdfsimg.vue8.5.效果 九、总结endl 八、文件的下载和删除功能 8.1.FastDFSClient.java Slf4j public class FastDFSClie…

websocket数据帧格式

客户端、服务端数据的交换,离不开数据帧格式的定义。因此,在实际讲解数据交换之前,我们先来看下WebSocket的数据帧格式。 WebSocket客户端、服务端通信的最小单位是帧(frame),由1个或多个帧组成一条完整的消…

Atcoder ABC339 C - Perfect Bus

Perfect Bus(完美的公交车) 时间限制:2s 内存限制:1024MB 【原题地址】 所有图片源自Atcoder,题目译文源自脚本Atcoder Better! 点击此处跳转至原题 【问题描述】 【输入格式】 【输出格式】 【样例1】 【样例输…

排序算法---计数排序

原创不易,转载请注明出处。欢迎点赞收藏~ 计数排序(Counting Sort)是一种线性时间复杂度的排序算法,其核心思想是通过统计待排序元素的个数来确定元素的相对位置,从而实现排序。 具体的计数排序算法步骤如下&#xff…

Netty Review - 直接内存的应用及源码分析

文章目录 Pre概述应用访问效率: 堆内存 VS 直接内存申请效率: 堆内存 VS 直接内存数据存储结构: 堆内存 VS 直接内存结论 ByteBuffer.allocateDirect 源码分析unsafe.allocateMemory(size) ---> C方法 JVM参数 -XX:MaxDirectMemorySize直接…

视觉slam十四讲学习笔记(五)非线性优化

已经知道,方程中的位姿可以由变换矩阵来描述,然后用李代数进行优化。观测方程由相机成像模型给出,其中内参是随相机固定的,而外参则是相机的位姿。 目录 前言 一、状态估计问题 1 最大后验与最大似然 2 最小二乘的引出 二、非…

JavaScript中null和undefined的区别

JavaScript中null和undefined是两个特殊的值,经常在编程中遇到。虽然它们经常被混淆,但它们有着不同的含义和用法。本文将详细介绍JavaScript中null和undefined的区别,帮助开发者更好地理解和使用它们。 首先,让我们来了解一下nu…

css篇---移动端适配的方案有哪几种

移动端适配 移动端适配是指同一个页面可以在不同的移动端设备上都有合理的布局。主流实现的方案有 响应式布局通过rem或者vw,vh 等实现不同设备有相同的比例而实现适配 首先需要了解viewport 【视口】 视口代表了一个可看见的多边形区域(通常来说是矩形&#xff0…

函数递归与迭代附n的阶乘+顺序打印一个整数的每一位数+求第n个斐波那契数

1. 什么是递归&#xff1f; 递归其实是一种解决问题的方法&#xff0c;在C语言中&#xff0c;递归就是函数自己调用自己。 下面是一个最简单的C语言递归代码&#xff1a; #include <stdio.h> int main() {printf("hehe\n");main();//main函数中⼜调⽤了main函数…

BBC英式口语~发音练习~笔记整理

参考资料 原视频地址&#xff1a; https://www.bilibili.com/video/BV1D7411n7bS/?spm_id_from333.1245.0.0&vd_source5986fc7c8e6d754f3ca44233573aeaff 笔记图片