Java8实战-总结50
Java8实战-总结50
- CompletableFuture:组合式异步编程
- 对多个异步任务进行流水线操作
- 对 Future 和 CompletableFuture 的回顾
- 响应 CompletableFuture 的 completion 事件
- 对最佳价格查询器应用的优化
CompletableFuture:组合式异步编程
对多个异步任务进行流水线操作
对 Future 和 CompletableFuture 的回顾
CompletableFuture
利用Lambda
表达式以声明式的API
提供了一种机制,能够用最有效的方式,非常容易地将多个以同步或异步方式执行复杂操作的任务结合到一起。为了更直观地感受一下使用CompletableFuture
在代码可读性上带来的巨大提升,可以尝试仅使用Java 7
中提供的特性,重新实现前面代码的功能。下面的代码展示了如何实现这一效果(利用Java 7
的方法合并两个Future
对象):
ExecutorService executor = Executors.newCachedThreadPool(); //创建一个ExecutorService将任务提交到线程池//创建一个查询欧元到美元转换汇率的Future
final Future<Double> futureRate = executor.submit(new Callable<Double>() {public Double call() { return exchangeService.getRate(Money.EUR, Money.USD); }}); Future<Double> futurePriceInUSD = executor.submit(new Callable<Double>() {public Double call() {double priceInEUR = shop.getPrice(product); //在第二个 Future中查询指定商店中特定商品的价格return priceInEUR * futureRate.get(); //在查找价格操作的同一个Future中,将价格和汇率做乘法计算出汇后价格}});
在上面的代码中,通过向执行器提交一个Callable
对象的方式创建了第一个Future
对象,向外部服务查询欧元和美元之间的转换汇率。紧接着,你创建了第二个Future
对象,查询指定商店中特定商品的欧元价格。最终,用与之前代码一样的方式,在同一个Future
中通过查询商店得到的欧元商品价格乘以汇率得到了最终的价格。注意,之前的代码中中如果使用thenCombineAsync
,不使用thenCombine
,像上面的代码一样,采用第三个Future
单独进行商品价格和汇率的乘法运算,效果是几乎相同的。这两种实现看起来没太大区别,原因是你只对两个Future
进行了合并。通过这两段代码,我们能看到创建流水线对同步和异步操作进行混合操作有多么简单,随着处理任务和需要合并结果数目的增加,这种声明式程序设计的优势也愈发明显。
你的“最佳价格查询器”应用基本已经完成,不过还缺失了一些元素。你会希望尽快将不同商店中的商品价格呈现给你的用户(这是车辆保险或者机票比价网站的典型需求),而不是像你之前那样,等所有的数据都完备之后再呈现。接下来的一节,你会了解如何通过响应CompletableFuture
的completion
事件实现这一功能(与此相反,“调用get
或者join
方法只会造成阻塞,直到CompletableFuture
完成才能继续往下运行)。
响应 CompletableFuture 的 completion 事件
下面这部分的所有示例代码都是通过在响应之前添加1秒钟的等待延迟模拟方法的远程调用。毫无疑问,现实世界中,你的应用访问各个远程服务时很可能遭遇无法预知的延迟,触发的原因多种多样,从服务器的负荷到网络的延迟,有些甚至是源于远程服务如何评估你应用的商业价值,即可能相对于其他的应用,你的应用每次查询的消耗时间更长。
由于这些原因,你希望购买的商品在某些商店的查询速度要比另一些商店更快。以下面的代码清单为例,使用randomDelay
方法取代原来的固定延迟。下面的代码是一个模拟生成0.5秒至2.5秒随机延迟的方法:
private static final Random random = new Random();
public static void randomDelay() {int delay = 500 + random.nextInt(2000); try { Thread.sleep(delay); } catch (InterruptedException e) { throw new RuntimeException(e); }
}
目前为止,你实现的findPrices
方法只有在取得所有商店的返回值时才显示商品的价格。而你希望的效果是,只要有商店返回商品价格就在第一时间显示返回值,不再等待那些还未返回的商店(有些甚至会发生超时)。你如何实现这种更进一步的改进要求呢?
对最佳价格查询器应用的优化
要避免的首要问题是,等待创建一个包含了所有价格的List
创建完成。你应该做的是直接处理CompletableFuture
流,这样每个CompletableFuture
都在为某个商店执行必要的操作。为了实现这一目标,在下面的代码清单中,会对前面代码实现的第一部分进行重构,实现findPricesStream
方法来生成一个由CompletableFuture
构成的流。重构findPrices
方法返回一个由Future
构成的流:
public Stream<CompletableFuture<String>> findPricesStream(String product) {return shops.stream().map(shop -> CompletableFuture.supplyAsync( () -> shop.getPrice(product), executor)).map(future -> future.thenApply(Quote::parse)).map(future -> future.thenCompose(quote -> CompletableFuture.supplyAsync(() -> Discount.applyDiscount(quote), executor)));
}
现在,你为findPricesStream
方法返回的Stream
添加了第四个map
操作,在此之前,你已经在该方法内部调用了三次 map
。这个新添加的操作其实很简单,只是在每个CompletableFuture
上注册一个操作,该操作会在CompletableFuture
完成执行后使用它的返回值。Java 8
的CompletableFuture
通过thenAccept
方法提供了这一功能,它接收CompletableFuture
执行完毕后的返回值做参数。在这里的例子中,该值是由Discount
服务返回的字符串值,它包含了提供请求商品的商店名称及折扣价格,你想要做的操作也很简单,只是将结果打印输出:
findPricesStream("myPhone").map(f -> f.thenAccept(System.out::println));
注意,和之前的thenCompose
和thenCombine
方法一样,thenAccept
方法也提供了一个异步版本,名为thenAcceptAsync
。异步版本的方法会对处理结果的消费者进行调度,从线程池中选择一个新的线程继续执行,不再由同一个线程完成CompletableFuture
的所有任务。因为你想要避免不必要的上下文切换,更重要的是你希望避免在等待线程上浪费时间,尽快响应CompletableFuture
的completion
事件,所以这里没有采用异步版本。由 于thenAccept
方法已经定义了如何处理CompletableFuture
返回的结果,一旦CompletableFuture
计算得到结果,它就返回一个CompletableFuture<Void>
。所以,map
操作返回的是一个Stream<CompletableFuture<Void>>
。对这个<CompletableFuture<Void>>
对象,你能做的事非常有限,只能等待其运行结束,不过这也是你所期望的。你还希望能给最慢的商店一些机会,让它有机会打印输出返回的价格。为了实现这一目的,你可以把构成Stream
的所有CompletableFuture<Void>
对象放到一个数组中,等待所有的任务执行完成,代码如下所示(响应CompletableFuture
的completion
事件):
CompletableFuture[] futures = findPricesStream("myPhone").map(f -> f.thenAccept(System.out::println)).toArray(size -> new CompletableFuture[size]);
CompletableFuture.allOf(futures).join();
allOf
工厂方法接收一个由CompletableFuture
构成的数组,数组中的所有CompletableFuture
对象执行完成之后,它返回一个CompletableFuture<Void>
对象。这意味着,如果你需要等待最初Stream
中的所有 CompletableFuture
对象执行完毕,对 allOf
方法返回的CompletableFuture
执行join
操作是个不错的主意。这个方法对“最佳价格查询器”应用也是有用的,因为你的用户可能会困惑是否后面还有一些价格没有返回,使用这个方法,你可以在执行完毕之后打印输出一条消息“All shops returned results or timed out”
。
然而在另一些场景中,你可能希望只要CompletableFuture
对象数组中有任何一个执行完毕就不再等待,比如,你正在查询两个汇率服务器,任何一个返回了结果都能满足你的需求。在这种情况下,你可以使用一个类似的工厂方法anyOf
。该方法接收一个CompletableFuture
对象构成的数组,返回由第一个执行完毕的CompletableFuture
对象的返回值构成的CompletableFuture<Object>
。
相关文章:
Java8实战-总结50
Java8实战-总结50 CompletableFuture:组合式异步编程对多个异步任务进行流水线操作对 Future 和 CompletableFuture 的回顾 响应 CompletableFuture 的 completion 事件对最佳价格查询器应用的优化 CompletableFuture:组合式异步编程 对多个异步任务进行…...
kicad源代码研究:参照Candence实现工程管理
创建工程: 创建工程和打开工程触发事件: KICAD_MANAGER_ACTIONS::newProjectKICAD_MANAGER_ACTIONS::openProjectnewProject和OpenProject事件响应具体实现,在KICAD_MANAGER_CONTROL类中实现: Go( &KICAD_MANAGER_CONTROL::…...
Asp.net core WebApi 配置自定义swaggerUI和中文注释,Jwt Bearer配置
1.创建asp.net core webApi项目 默认会引入swagger的Nuget包 <PackageReference Include"Swashbuckle.AspNetCore" Version"6.2.3" />2.配置基本信息和中文注释(默认是没有中文注释的) 2.1创建一个新的controller using Micr…...
DNS 查询结果逐行解释
文章目录 FlagsADDITIONALANSWER SECTIONQuery timeSERVERWHENDNS PortAuthoritative answer权威DNS服务器Non-authoritative answer推荐阅读 DNS查询后,查询结果一般如下: mirrorUbuntu22:~$ dig www.baidu.com; <<>> DiG 9.18.12-0ubuntu0…...
ArcGIS制作广场游客聚集状态及密度图
文章目录 一、加载实验数据二、平均最近邻法介绍1. 平均最近邻工具2. 广场游客聚集状态3. 结果分析三、游客密度制图一、加载实验数据 二、平均最近邻法介绍 1. 平均最近邻工具 “平均最近邻”工具将返回五个值:“平均观测距离”、“预期平均距离”、“最近邻指数”、z 得分和…...
同旺科技 USB TO SPI / I2C --- 调试W5500_TCP Client接收数据
所需设备: 内附链接 1、USB转SPI_I2C适配器(专业版); 首先,连接W5500模块与同旺科技USB TO SPI / I2C适配器,如下图: 发送数据6个字节的数据:0x11,0x22,0x33,0x44,0x55,0x66 在专业版调试软件中编辑指令,…...
MQ - KAFKA 高级篇
kafak是一个分布式流处理平台,提供消息持久化,基于发布-订阅的方式的消息中间件,同时通过消费端配置相同的groupId支持点对点通信。 ##适用场景: 构造实时流数据管道,用于系统或应用之间可靠的消息传输.数据采集及处理,例如连接到一个数据库系统,捕捉表…...
如何快速查找最后(最右侧)隐藏列
实例需求:定位工作表中的最后(最右侧)隐藏列,处理其中的数据。 通常思路是从工作表最后列开始,倒序检查每个列,直到找到隐藏列或者检查完毕(无隐藏列)。 Sub LastColumn()Dim visR…...
精密制造ERP系统包含哪些模块?精密制造ERP软件是做什么的
不同种类的精密制造成品有区别化的制造工序、工艺流转、品质标准、生产成本、营销策略等,而多工厂、多仓库、多车间、多部门协同问题却是不少精密制造企业遇到的管理难题。 有些产品结构较为复杂,制造工序繁多,关联业务多,传统的…...
TypeScript 的高级技巧
1 — 高级类型(Advanced Types) 使用 TypeScript 的高级类型,如映射类型和条件类型,可以基于现有类型构建新类型。通过使用这些类型,您可以在强类型系统中更改和操作类型,从而使您的代码具有更大的灵活性和…...
TiDB 7.x 源码编译之 TiDB Server 篇,及新特性详解
本文将介绍如何编译 TiDB Server 源码。以及阐释 TiDB Server 7.x 的部分新特性。 TiDB v7.5.0 LTS 计划于 2023 年 11 月正式 Release,目前代码虽未冻结,但已经可以看到 Alpha 版本的 Code 了,本文代码将以 v7.5.0-alpha 为基准。 TiDB Se…...
Hadoop实验putty文件
🔥博客主页: A_SHOWY🎥系列专栏:力扣刷题总结录 数据结构 云计算 数字图像处理 很多朋友反馈做hadoop实验中的putty找不到Connection-SSH-Auth路径下找不到Private key for authentication私有密钥,无法将转…...
研发人员绩效考核难题及解决措施
研发部门是技术型企业的核心人员,研发人员的设计贯穿着产品实现过程包括后续的持续改进。倘若研发人员的设计源头得以保障,那么后续工作包括研发人员的绩效考核,相对简单。接下来华恒智信便根据多年来从事的人力资源相关的服务经验为您对于研…...
Inference with C# BERT NLP Deep Learning and ONNX Runtime
目录 效果 测试一 测试二 测试三 模型信息 项目 代码 下载 Inference with C# BERT NLP Deep Learning and ONNX Runtime 效果 测试一 Context :Bob is walking through the woods collecting blueberries and strawberries to make a pie. Question …...
6、原型模式(Prototype Pattern,不常用)
原型模式指通过调用原型实例的Clone方法或其他手段来创建对象。 原型模式属于创建型设计模式,它以当前对象为原型(蓝本)来创建另一个新的对象,而无须知道创建的细节。原型模式在Java中通常使用Clone技术实现,在JavaSc…...
图像万物分割——Segment Anything算法解析与模型推理
一、概述 在视觉任务中,图像分割任务是一个很广泛的领域,应用于交互式分割,边缘检测,超像素化,感兴趣目标生成,前景分割,语义分割,实例分割,泛视分割等。 交互式分割&am…...
Redis实战篇笔记(最终篇)
Redis实战篇笔记(七) 文章目录 Redis实战篇笔记(七)前言达人探店发布和查看探店笔记点赞点赞排行榜 好友关注关注和取关共同关注关注推送关注推荐的实现 总结 前言 本系列文章是Redis实战篇笔记的最后一篇,那么到这里…...
游戏配置表的导入使用
游戏配置表是游戏策划的标配,如下图: 那么程序怎么把这张配置表导入使用? 1.首先,利用命令行把Excel格式的文件转化成Json格式: json-excel\json-excel json Tables\ Data\copy Data\CharacterDefine.txt ..\Clien…...
❀dialog命令运用于linux❀
目录 ❀dialog命令运用于linux❀ msgbox部件(消息框) yesno部件(yesno框) inputbox部件(输入文本框) textbox部件(文本框) menu部件(菜单框) fselect部…...
【算法】蓝桥杯2013国C 横向打印二叉树 题解
文章目录 题目链接题目描述输入格式输出格式样例自己的样例输入自己的样例输出 思路整体思路存储二叉搜索树中序遍历并存储计算目标数的行号dfs遍历并写入数组初始化和处理输入输出初始化处理输入处理输出 完整的代码如下 结束语更新初始化的修改存储二叉搜索树的修改中序遍历和…...
XunSearch 讯搜 error: storage size of ‘methods_bufferevent’ isn’t known
报错: error: storage size of ‘methods_bufferevent’ isn’t known CentOS8.0安装迅搜(XunSearch)引擎报错的解决办法 比较完整的文档 http://www.xunsearch.com/download/xs_quickstart.pdf 官方安装文档 http://www.xunsearch.com/doc/php/guide/start.in…...
基于AWS Serverless的Glue服务进行ETL(提取、转换和加载)数据分析(三)——serverless数据分析
3 serverless数据分析 大纲 3 serverless数据分析3.1 创建Lambda3.2 创建API Gateway3.3 结果3.4 总结 3.1 创建Lambda 在Lambda中,我们将使用python3作为代码语言。 步骤图例1、入口2、创建(我们选择使用python3.7)3、IAM权限(…...
08、分析测试执行时间及获取pytest帮助
官方用例 # content of test_slow_func.py import pytest from time import sleeppytest.mark.parametrize(delay,(1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,1.0,0.1,0.2,0,3)) def test_slow_func(delay):print("test_slow_func {}".format(delay))sleep(delay)assert…...
视频集中存储/智能分析融合云平台EasyCVR平台接入rtsp,突然断流是什么原因?
安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快,可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等,以及支持厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…...
JavaScript 复杂的<三元运算符和比较操作>的组合--案例(一)
在逆向的时候,碰上有些复杂的js代码,逻辑弄得人有点混; 因此本帖用来记录一些棘手的代码,方便自己记忆,也让大家拓展认识~ ----前言 内容: function(e, t, n) {try {1 (e "{" e[0] ? JSON.parse(e) : JSON.parse(webInstace.shell(e))).Status || 200 e.Code…...
uniapp搭建内网映射测试https域名
搭建Https域名服务器 使用github的frp搭建,使用宝塔申请免费https证书,需要先关闭宝塔nginx的反向代理,申请完域名后再开启反向代理即可。 教程 新版frp搭建教程 启动命令 服务器端 sudo systemctl start frps本地 cd D:\软件安装包\f…...
国防科技大博士招生入学考试【50+论文主观题】
目录 回答模板大意创新和学术价值启发 论文分类(根据问题/场景分类)数学问题Efficient Multiset Synchronization(高效的多集同步【简单集合/可逆计数Bloom过滤器】)大意创新和学术价值启发 An empirical study of Bayesian netwo…...
CUDA简介——编程模式
1. 引言 前序博客: CUDA简介——基本概念 CPU是用于控制的。即,host控制整个程序流程: 1)程序以Host代码main函数开始,然后顺序执行。 Host代码是顺序执行的,并执行在CPU之上。Host代码会负责Launch ke…...
Linux 软件安装
目录 一、Linux 1、Linux异常解决 1、JDK安装 1、Linux卸载JDK 2、Linux安装JDK 2、Redis安装 一、Linux 1、Linux异常解决 1、Another app is currently holding the yum lock; waiting for it to exit... 解决办法: rm -f /var/run/yum.pid1、杀死这个应用程序 ps a…...
flask之邮件发送
一、安装Flask-Mail扩展 pip install Flask-Mail二、配置Flask-Mail 格式:app.config[参数]值 三、实现方法 3.1、Mail类 常用类方法 3.2、Message类,它封装了一封电子邮件。构造函数参数如下: flask-mail.Message(subject, recipient…...
成都网站建设推荐q479185700顶上/app开发需要多少钱
iOS/Android DevCamp:移动开发者大本营 即将来袭 2012-06-18 12:20|54次阅读|来源:CSDN【已有0条评论】发表评论 关键词:iOS/Android,DevCamp|作者:张宁|收藏这篇资讯 每年的WWDC都得到了移动应用开发业界的重点关注,今…...
wordpress 注册邮件设置密码/网站制作报价表
布尔函数标准型及化简1.逻辑函数及其标准型2.电路优化2.1成本标准2.2成本与速度的矛盾2.3与或式(或与式)的门输入成本2.4代数法优化电路表达式3.门的传播延迟3.1延迟模型3.2时间测量3.3冒险(冲突)现象1.逻辑函数及其标准型 ●n变…...
wordpress使用手机号登录/长尾关键词查询
【流媒體】Android 实时视频采集—MediaRecoder录制 SkySeraph Mar 31st 2012 Email:skyseraph00163.com 流媒体系列: http://skyseraph.com/2012/04/11/Media/流媒体专题/ 0 啰嗦 本篇的存在只是为系列的连贯性,其实在前面系列博文中对Med…...
网站建立平台 cms/by网站域名
地理数据的坐标主要分为两种方式:地理坐标和投影坐标。地理坐标是球面坐标,简单来说就是使用经纬度来表示位置坐标,投影是按照一定的数学模型将球面坐标投影到几何体后,用平面坐标(x和y)来表示位置信息。工作中我们经常会用到地理…...
不能制作网页的软件有哪些/windows优化大师是哪个公司的
我想在这里做些奇怪的事情。我需要从一个守护进程启动一个logcat进程,该守护进程将在后台运行并打印到终端,而无需控制stdin。它是用于记录日志的,因此理想情况下logcat将打印日志消息,同时仍允许用户输入标准命令并从Shell初始化…...
如何建设网站推广平台/搜索软件排行榜前十名
分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请点击http://www.captainbed.net 是值传递。Java语言的方法调用只支持参数的值传递。当一个对象实例作为一个参数被传递到方法中时&am…...