当前位置: 首页 > news >正文

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进行了合并。通过这两段代码,我们能看到创建流水线对同步和异步操作进行混合操作有多么简单,随着处理任务和需要合并结果数目的增加,这种声明式程序设计的优势也愈发明显。

你的“最佳价格查询器”应用基本已经完成,不过还缺失了一些元素。你会希望尽快将不同商店中的商品价格呈现给你的用户(这是车辆保险或者机票比价网站的典型需求),而不是像你之前那样,等所有的数据都完备之后再呈现。接下来的一节,你会了解如何通过响应CompletableFuturecompletion事件实现这一功能(与此相反,“调用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 8CompletableFuture通过thenAccept方法提供了这一功能,它接收CompletableFuture执行完毕后的返回值做参数。在这里的例子中,该值是由Discount服务返回的字符串值,它包含了提供请求商品的商店名称及折扣价格,你想要做的操作也很简单,只是将结果打印输出:

findPricesStream("myPhone").map(f -> f.thenAccept(System.out::println)); 

注意,和之前的thenComposethenCombine方法一样,thenAccept方法也提供了一个异步版本,名为thenAcceptAsync。异步版本的方法会对处理结果的消费者进行调度,从线程池中选择一个新的线程继续执行,不再由同一个线程完成CompletableFuture的所有任务。因为你想要避免不必要的上下文切换,更重要的是你希望避免在等待线程上浪费时间,尽快响应CompletableFuturecompletion事件,所以这里没有采用异步版本。由 于thenAccept方法已经定义了如何处理CompletableFuture返回的结果,一旦CompletableFuture计算得到结果,它就返回一个CompletableFuture<Void>。所以,map操作返回的是一个Stream<CompletableFuture<Void>>。对这个<CompletableFuture<Void>>对象,你能做的事非常有限,只能等待其运行结束,不过这也是你所期望的。你还希望能给最慢的商店一些机会,让它有机会打印输出返回的价格。为了实现这一目的,你可以把构成Stream的所有CompletableFuture<Void>对象放到一个数组中,等待所有的任务执行完成,代码如下所示(响应CompletableFuturecompletion事件):

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&#xff1a;组合式异步编程对多个异步任务进行流水线操作对 Future 和 CompletableFuture 的回顾 响应 CompletableFuture 的 completion 事件对最佳价格查询器应用的优化 CompletableFuture&#xff1a;组合式异步编程 对多个异步任务进行…...

kicad源代码研究:参照Candence实现工程管理

创建工程&#xff1a; 创建工程和打开工程触发事件&#xff1a; KICAD_MANAGER_ACTIONS::newProjectKICAD_MANAGER_ACTIONS::openProjectnewProject和OpenProject事件响应具体实现&#xff0c;在KICAD_MANAGER_CONTROL类中实现&#xff1a; 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.配置基本信息和中文注释&#xff08;默认是没有中文注释的&#xff09; 2.1创建一个新的controller using Micr…...

DNS 查询结果逐行解释

文章目录 FlagsADDITIONALANSWER SECTIONQuery timeSERVERWHENDNS PortAuthoritative answer权威DNS服务器Non-authoritative answer推荐阅读 DNS查询后&#xff0c;查询结果一般如下&#xff1a; mirrorUbuntu22:~$ dig www.baidu.com; <<>> DiG 9.18.12-0ubuntu0…...

ArcGIS制作广场游客聚集状态及密度图

文章目录 一、加载实验数据二、平均最近邻法介绍1. 平均最近邻工具2. 广场游客聚集状态3. 结果分析三、游客密度制图一、加载实验数据 二、平均最近邻法介绍 1. 平均最近邻工具 “平均最近邻”工具将返回五个值:“平均观测距离”、“预期平均距离”、“最近邻指数”、z 得分和…...

同旺科技 USB TO SPI / I2C --- 调试W5500_TCP Client接收数据

所需设备&#xff1a; 内附链接 1、USB转SPI_I2C适配器(专业版); 首先&#xff0c;连接W5500模块与同旺科技USB TO SPI / I2C适配器&#xff0c;如下图&#xff1a; 发送数据6个字节的数据&#xff1a;0x11,0x22,0x33,0x44,0x55,0x66 在专业版调试软件中编辑指令&#xff0c…...

MQ - KAFKA 高级篇

kafak是一个分布式流处理平台,提供消息持久化,基于发布-订阅的方式的消息中间件&#xff0c;同时通过消费端配置相同的groupId支持点对点通信。 ##适用场景&#xff1a; 构造实时流数据管道,用于系统或应用之间可靠的消息传输.数据采集及处理,例如连接到一个数据库系统,捕捉表…...

如何快速查找最后(最右侧)隐藏列

实例需求&#xff1a;定位工作表中的最后&#xff08;最右侧&#xff09;隐藏列&#xff0c;处理其中的数据。 通常思路是从工作表最后列开始&#xff0c;倒序检查每个列&#xff0c;直到找到隐藏列或者检查完毕&#xff08;无隐藏列&#xff09;。 Sub LastColumn()Dim visR…...

精密制造ERP系统包含哪些模块?精密制造ERP软件是做什么的

不同种类的精密制造成品有区别化的制造工序、工艺流转、品质标准、生产成本、营销策略等&#xff0c;而多工厂、多仓库、多车间、多部门协同问题却是不少精密制造企业遇到的管理难题。 有些产品结构较为复杂&#xff0c;制造工序繁多&#xff0c;关联业务多&#xff0c;传统的…...

TypeScript 的高级技巧

1 — 高级类型&#xff08;Advanced Types&#xff09; 使用 TypeScript 的高级类型&#xff0c;如映射类型和条件类型&#xff0c;可以基于现有类型构建新类型。通过使用这些类型&#xff0c;您可以在强类型系统中更改和操作类型&#xff0c;从而使您的代码具有更大的灵活性和…...

TiDB 7.x 源码编译之 TiDB Server 篇,及新特性详解

本文将介绍如何编译 TiDB Server 源码。以及阐释 TiDB Server 7.x 的部分新特性。 TiDB v7.5.0 LTS 计划于 2023 年 11 月正式 Release&#xff0c;目前代码虽未冻结&#xff0c;但已经可以看到 Alpha 版本的 Code 了&#xff0c;本文代码将以 v7.5.0-alpha 为基准。 TiDB Se…...

Hadoop实验putty文件

&#x1f525;博客主页&#xff1a; A_SHOWY&#x1f3a5;系列专栏&#xff1a;力扣刷题总结录 数据结构 云计算 数字图像处理 很多朋友反馈做hadoop实验中的putty找不到Connection-SSH-Auth路径下找不到Private key for authentication私有密钥&#xff0c;无法将转…...

研发人员绩效考核难题及解决措施

研发部门是技术型企业的核心人员&#xff0c;研发人员的设计贯穿着产品实现过程包括后续的持续改进。倘若研发人员的设计源头得以保障&#xff0c;那么后续工作包括研发人员的绩效考核&#xff0c;相对简单。接下来华恒智信便根据多年来从事的人力资源相关的服务经验为您对于研…...

Inference with C# BERT NLP Deep Learning and ONNX Runtime

目录 效果 测试一 测试二 测试三 模型信息 项目 代码 下载 Inference with C# BERT NLP Deep Learning and ONNX Runtime 效果 测试一 Context &#xff1a;Bob is walking through the woods collecting blueberries and strawberries to make a pie. Question …...

6、原型模式(Prototype Pattern,不常用)

原型模式指通过调用原型实例的Clone方法或其他手段来创建对象。 原型模式属于创建型设计模式&#xff0c;它以当前对象为原型&#xff08;蓝本&#xff09;来创建另一个新的对象&#xff0c;而无须知道创建的细节。原型模式在Java中通常使用Clone技术实现&#xff0c;在JavaSc…...

图像万物分割——Segment Anything算法解析与模型推理

一、概述 在视觉任务中&#xff0c;图像分割任务是一个很广泛的领域&#xff0c;应用于交互式分割&#xff0c;边缘检测&#xff0c;超像素化&#xff0c;感兴趣目标生成&#xff0c;前景分割&#xff0c;语义分割&#xff0c;实例分割&#xff0c;泛视分割等。 交互式分割&am…...

Redis实战篇笔记(最终篇)

Redis实战篇笔记&#xff08;七&#xff09; 文章目录 Redis实战篇笔记&#xff08;七&#xff09;前言达人探店发布和查看探店笔记点赞点赞排行榜 好友关注关注和取关共同关注关注推送关注推荐的实现 总结 前言 本系列文章是Redis实战篇笔记的最后一篇&#xff0c;那么到这里…...

游戏配置表的导入使用

游戏配置表是游戏策划的标配&#xff0c;如下图&#xff1a; 那么程序怎么把这张配置表导入使用&#xff1f; 1.首先&#xff0c;利用命令行把Excel格式的文件转化成Json格式&#xff1a; json-excel\json-excel json Tables\ Data\copy Data\CharacterDefine.txt ..\Clien…...

❀dialog命令运用于linux❀

目录 ❀dialog命令运用于linux❀ msgbox部件&#xff08;消息框&#xff09; yesno部件&#xff08;yesno框&#xff09; inputbox部件&#xff08;输入文本框&#xff09; textbox部件&#xff08;文本框&#xff09; menu部件&#xff08;菜单框&#xff09; fselect部…...

【算法】蓝桥杯2013国C 横向打印二叉树 题解

文章目录 题目链接题目描述输入格式输出格式样例自己的样例输入自己的样例输出 思路整体思路存储二叉搜索树中序遍历并存储计算目标数的行号dfs遍历并写入数组初始化和处理输入输出初始化处理输入处理输出 完整的代码如下 结束语更新初始化的修改存储二叉搜索树的修改中序遍历和…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录

ASP.NET Core 是一个跨平台的开源框架&#xff0c;用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录&#xff0c;以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

Python ROS2【机器人中间件框架】 简介

销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行

项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战&#xff0c;克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

【网络安全】开源系统getshell漏洞挖掘

审计过程&#xff1a; 在入口文件admin/index.php中&#xff1a; 用户可以通过m,c,a等参数控制加载的文件和方法&#xff0c;在app/system/entrance.php中存在重点代码&#xff1a; 当M_TYPE system并且M_MODULE include时&#xff0c;会设置常量PATH_OWN_FILE为PATH_APP.M_T…...