阿里图标库谁做的网站/关键词挖掘工具站
需求
有一家商店提供的价格是以欧元(EUR)计价的,但是你希望以美元的方式提供给你的客户。你可以用异步的方式向商店查询指定商品的价格,同时从远程的汇率服务那里查到欧元和美元之间的汇率。当二者都结束时,再将这两个结果结合起来,用返回的商品价格乘以当时的汇率,得到以美元计价的商品价格。
实现源码
public class ExchangeService {public enum Money {USD(1.0), EUR(1.35387), GBP(1.69715), CAD(.92106), MXN(.07683);private final double rate;Money(double rate) {this.rate = rate;}}public static double getRate(Money source, Money destination) {return getRateWithDelay(source, destination);}private static double getRateWithDelay(Money source, Money destination) {Util.delay();return destination.rate / source.rate;}
}public class BestPriceFinder {private final List<Shop> shops = Arrays.asList(new Shop("BestPrice"),new Shop("LetsSaveBig"),new Shop("MyFavoriteShop"),new Shop("BuyItAll") new Shop("ShopEasy"));private final Executor executor = Executors.newFixedThreadPool(shops.size(), ExecuterThreadFactoryBuilder.build());
}
实现方案
你对一个CompletableFuture对象调用了thenCompose
方法,并向其传递了第二个CompletableFuture,而第二个CompletableFuture又需要使用第一个CompletableFuture的执行结果作为输入。但是,另一种比较常见的情况是,你需要将两个完全不相干的CompletableFuture对象的结果整合起来,而且你也不希望等到第一个任务完全结束才开始第二项任务。你应该使用thenCombine
方法。thenCombine方法也提供有一个Async的版本。这里,如果使用thenCombineAsync
会导致BiFunction中定义的合并操作被提交到线程池中,由另一个任务以异步的方式执行。
方案1:
public List<String> findPricesInUSD(String product) {List<CompletableFuture<Double>> priceFutures = new ArrayList<>();for (Shop shop : shops) {CompletableFuture<Double> futurePriceInUSD = CompletableFuture.supplyAsync(() -> shop.getPrice(product), executor).thenCombine(CompletableFuture.supplyAsync(() -> ExchangeService.getRate(Money.EUR, Money.USD), executor), (price, rate) -> price * rate);priceFutures.add(futurePriceInUSD);}List<String> prices = priceFutures.stream().map(CompletableFuture::join).map(price -> " price is " + price).collect(Collectors.toList());return prices;
}
方案2:
public List<String> findPricesInUSD2(String product) {List<CompletableFuture<String>> priceFutures = new ArrayList<>();for (Shop shop : shops) {CompletableFuture<String> futurePriceInUSD = CompletableFuture.supplyAsync(() -> shop.getPrice(product), executor).thenCombine(CompletableFuture.supplyAsync(() -> ExchangeService.getRate(Money.EUR, Money.USD), executor), (price, rate) -> price * rate).thenApply(price -> shop.getName() + " price is " + price);priceFutures.add(futurePriceInUSD);}List<String> prices = priceFutures.stream().map(CompletableFuture::join).collect(Collectors.toList());return prices;
}
方案3:
public List<String> findPricesInUSD3(String product) {List<CompletableFuture<String>> priceFutures = shops.stream().map(shop -> CompletableFuture.supplyAsync(() -> shop.getPrice(product)).thenCombine(CompletableFuture.supplyAsync(() -> ExchangeService.getRate(Money.EUR, Money.USD)), (price, rate) -> price * rate).thenApply(price -> shop.getName() + " price is " + price)).collect(Collectors.toList());List<String> prices = priceFutures.stream().map(CompletableFuture::join).collect(Collectors.toList());return prices;
}
方案4:使用Java 7中提供的特性完成上述功能
// 为了更直观地感受一下使用CompletableFuture在代码可读性上带来的巨大提升,尝试仅使用Java 7中提供的特性实现以下如上实现
public List<String> findPricesInUSDJava7(String product) {ExecutorService executor = Executors.newCachedThreadPool();List<Future<Double>> priceFutures = new ArrayList<>();for (Shop shop : shops) {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() {try {double priceInEUR = shop.getPrice(product);return priceInEUR * futureRate.get();} catch (InterruptedException | ExecutionException e) {throw new RuntimeException(e.getMessage(), e);}}});priceFutures.add(futurePriceInUSD);}List<String> prices = new ArrayList<>();for (Future<Double> priceFuture : priceFutures) {try {prices.add(" price is " + priceFuture.get());}catch (ExecutionException | InterruptedException e) {e.printStackTrace();}}return prices;
}
我们能看到创建流水线对同步和异步操作进行混合操作有多么简单,随着处理任务和需要合并结果数目的增加,这种声明式程序设计的优势也愈发明显。
测试
public static void main(String[] args) {StopWatch stopWatch = new StopWatch("性能比较");execute("combined USD findPricesInUSDJava7", () -> bestPriceFinder.findPricesInUSDJava7("myPhone27S"), stopWatch);execute("combined USD CompletableFuture", () -> bestPriceFinder.findPricesInUSD("myPhone27S"), stopWatch);execute("combined USD CompletableFuture v2", () -> bestPriceFinder.findPricesInUSD2("myPhone27S"), stopWatch);execute("combined USD CompletableFuture v3", () -> bestPriceFinder.findPricesInUSD3("myPhone27S"), stopWatch);StopWatchUtils.logStopWatch(stopWatch);
}
private static void execute(String msg, Supplier<List<String>> s, StopWatch stopWatch) {stopWatch.start(msg);System.out.println(s.get());stopWatch.stop();System.out.println();
}[ price is 91.040141702717, price is 125.1710573102377, price is 158.16078708139523, price is 136.45612204497712, price is 130.0591978746988][ price is 145.62246618545896, price is 123.78887748261509, price is 142.17561724598045, price is 147.48700495707948, price is 148.2901027867818][BestPrice price is 126.3823279607243, LetsSaveBig price is 124.52723804111048, MyFavoriteShop price is 129.1051274535831, BuyItAll price is 114.36072566615553, ShopEasy price is 121.11783256695436][BestPrice price is 168.06251816668828, LetsSaveBig price is 148.38498827435606, MyFavoriteShop price is 119.0272869408407, BuyItAll price is 115.15446874021768, ShopEasy price is 153.35355439427738]性能比较 total cost time = 6045 ms
combined USD findPricesInUSDJava7 : 1008 ms, 16.67%
combined USD CompletableFuture : 2009 ms, 33.23%
combined USD CompletableFuture v2 : 2015 ms, 33.33%
combined USD CompletableFuture v3 : 1012 ms, 16.74%
相关文章:

对产品实现汇率换算服务(将两个CompletableFuture对象整合起来,无论它们是否存在依赖)
需求 有一家商店提供的价格是以欧元(EUR)计价的,但是你希望以美元的方式提供给你的客户。你可以用异步的方式向商店查询指定商品的价格,同时从远程的汇率服务那里查到欧元和美元之间的汇率。当二者都结束时,再将这两个…...

数据库期末考前复习题(单选+多选+判断+解答)
文章目录 #数据库考前复习题一、 选择1.单选题2.多选题 二、判断题三、解答请描述数据库中的三大范式关系型数据库ACID特性 #数据库考前复习题 一、 选择 1.单选题 1.使用limit进行分页查询,其中每页10条数据,查询第5页应该写为? SELECT *…...

Ubuntu22.04源码安装ROS-noetic(ROS1非ROS2),编译运行VINS-MONO
1. Ubuntu22.04源码编译安装ROS-noetic 由于22.04默认安装ROS2,但很多仓库都是基于ROS1的,不想重装系统,参考这两个博客安装了ROS-noetic: 博客1. https://blog.csdn.net/Drknown/article/details/128701624博客2. https://zhua…...

窗口管理工具 Mosaic mac中文版功能特点
MosAIc mac是一种窗口管理工具,可帮助您在计算机屏幕上有效地组织和管理多个应用程序窗口。它提供了一种直观的方式来调整和排列窗口,以最大化工作效率。 MosAIc mac窗口管理软件功能和特点 窗口布局:MosAIc允许您选择不同的窗口布局&#x…...

Sql Prompt 10下载安装图文教程
在操作过程中,请暂时关闭你的防病毒软件,以免其误报导致操作失败。 资源 SQL Prompt 10 https://www.aliyundrive.com/s/QuMWkvE1Sv6 点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线查看&…...

VB.net webbrowser 自定义下载接口实现
使用《VB.net webbrowser 如何实现自定义下载 IDownloadManager》中的控件ExtendedWebBrowser(下载控件),并扩展了NewWindow2。 使用ExtendedWebBrowser_1过程中,遇到很多问题,花了几天时间,终于解决了所有…...

Android 启动优化案例-WebView非预期初始化排查
作者:邹阿涛涛涛涛涛涛 去年年底做启动优化时,有个比较好玩的 case 给大家分享下,希望大家能从我的分享里 get 到我在做一些问题排查修复时是怎么看上去又low又土又高效的。 1. 现象 在我们使用 Perfetto 进行app 启动过程性能观测时&#…...

【MATLAB源码-第80期】基于蚯蚓优化算法(EOA)的无人机三维路径规划,输出做短路径图和适应度曲线
操作环境: MATLAB 2022a 1、算法描述 蚯蚓优化算法(Earthworm Optimisation Algorithm, EOA)是一种启发式算法,灵感来源于蚯蚓在自然界中的行为模式。蚯蚓优化算法主要模仿了蚯蚓在寻找食物和逃避天敌时的行为策略。以下是蚯蚓…...

树状图怎么画?推荐这个好用的在线树状图软件!
在日常工作和学习中,我们需要用到各种各样的图表,树状图是其中之一。 树状图是什么? 树状图是一种层次式的图形结构,可以用来展示数据之间的关系,并且可以在一定程度上提高工作和学习的效率。 树状图通常用来表示…...

C#学习相关系列之Linq用法---where和select用法(二)
一、select用法 Linq中的select可以便捷使我们的对List中的每一项进行操作,生成新的列表。 var ttlist.select(p>p10); //select括号内为List中的每一项,p10即为对每一项的操作,即对每项都加10生成新的List 用法实例: 1、la…...

后端返回 date 时间日期格式为 UTC 格式字符串,形如 2022-08-11T10:50:31.050+00:00前端如何修改为yyyy-mm-dd
在不指定任何特殊配置的情况下,返回的 date 类型的字段会自动转成 UTC 格式字符串,形如 2022-08-11T10:50:31.05000:00。 前端如何处理? vue举例 utils 下新建 mixins.js文件 // minins.js文件 import Vue from "vue"; import {…...

【万字长文】前端性能优化实践 | 京东云技术团队
一、引言 从一个假死页面引发的思考: 作为前端开发,除了要攻克页面难点,也要有更深的自我目标,性能优化是自我提升中很重要的一环; 在前端开发中,会偶遇到页面假死的现象, 是因为当js有大量计算…...

WPF位图效果
Windows Presentation Foundation (WPF) 提供了许多位图效果,可以让你创建复杂的图形和动画。这些效果包括,但不限于以下几种: 模糊效果 (BlurEffect):这一效果可以使图像模糊,你可以设置模糊半径来控制模糊程度。投影…...

CFI(Common Flash Interface)简介
CFI定义了符合CFI规则设备的基本Query接口,包括已知或待拟定的flash Read/Write/Program/Erase控制接口。Query接口以结构体形式定义与flash设备相关的关键参数,但是CFI不会对单个flash设备厂家指定详细的指令集、状态轮询模式以及软件算法。 1.操作概要…...

linux、windows 查看java等进程占用资源情况
linux查看进程占用资源情况: top -o %MEM -b -n 1 | grep java | awk {print "PID: "$1" \t 虚拟内存: "$5" \t 物理内存: "$6" \t 共享内存: "$7" \t CPU使用率: "$9"% \t 内存使用率: "$10"%&…...

听GPT 讲Rust源代码--library/core/src(7)
题图来自 Hello, crustaceans.[1] File: rust/library/core/src/ptr/metadata.rs 在Rust的源代码中,rust/library/core/src/ptr/metadata.rs 文件的作用是定义了与指针(ptr)和元数据(metadata)相关的结构体和 trait&am…...

html:lang属性设置为中文zh-CN
默认的lang属性 <html lang"en"> </html>声明网页语言格式: 语言-国家/地区示例 <html lang"zh-CN"> </html>ISO 639-1 语言代码 语言ISO 代码Chinese (简体)zh ISO 639-1 国家/地区代码 国家/地区ISO 代码CHINA…...

滴滴 Redis 异地多活的演进历程
为了更好的做好容灾保障,使业务能够应对机房级别的故障,滴滴的存储服务都在多机房进行部署。本文简要分析了 Redis 实现异地多活的几种思路,以及滴滴 Redis 异地多活架构演进过程中遇到的主要问题和解决方法,抛砖引玉,…...

前端实现页面内容的截图与下载(html2canvas)
今天是一个发文的好日子😀~ 👇👇👇 一个需求,要截取页面中的内容并截图保存,来看一看我是怎么实现的吧: 这里需要使用到插件--html2canvas 1.安装并引入html2canvas npm install html2canv…...

VS2017 IDE 编译时的 X86、x64位 是干什么的
指定编译出的程序是x86架构下的32位程序还是64位程序 VS2017项目配置X86改配置x64位_winform:把项目由x86改为x64-CSDN博客 vs平台选项:Any CPU,x86,x64_vs anycpu-CSDN博客...

微信小程序 解决tab页切换过快 数据出错问题
具体问题:切换tab页切换过快时,上一个列表接口未响应完和当前列表数据冲突 出现数据错误 具体效果如下: 解决方式:原理 通过判断是否存在request 存在中断 并发送新请求 不存在新请求 let shouldAbort false; // 添加一个中断标志 let re…...

Taro编译警告解决方案:Error: chunk common [mini-css-extract-plugin]
文章目录 1. 背景2. 问题分析3. 解决方案3.1 更新 Taro 版本3.2 更新相关依赖3.3 调整 webpack 配置3.4 检查依赖版本 4. 拓展与分析4.1 拓展4.2 避免不必要的依赖4.3 查阅 Taro GitHub 仓库 5. 总结 🎉欢迎来到Java学习路线专栏~Taro编译警告解决方案:E…...

基于JavaWeb+SpringBoot+Vue电子商城微信小程序系统的设计和实现
基于JavaWebSpringBootVue电子商城微信小程序系统的设计和实现 源码获取入口前言系统设计功能截图Lun文目录订阅经典源码专栏Java项目精品实战案例《500套》 源码获取 源码获取入口 前言 身处互联网时代,互联网无形中影响着人们的吃穿住行,人们享受着不…...

JS进阶——作用域、解构、箭头函数
1、作用域 作用域(scope)规定了变量能够被访问的“范围”,离开了这个“范围”变量便不能被访问。 1.1 局部作用域 局部作用域可分为函数作用域和块作用域。 1.1.1 函数作用域 在函数内部声明的变量只能在函数内部被访问,外部无…...

centos下安装mysql8版本
1、如果服务器没有wget,先下载wget工具 sudo yum install wget 2、下载指定mysql版本的tar包 sudo wget https://downloads.mysql.com/archives/get/p/23/file/mysql-8.0.21-1.el7.x86_64.rpm-bundle.tar 3、解压tar包 sudo tar -xvf mysql-8.0.21-1.el7.x86_64.rpm…...

C++面试常考手写题目
C面试常考手写题目 vectorstringauto_ptrshared_ptrunique_ptrweak_ptrsingleton快排非递归heapheap_sortmerge_sort vector #include <bits/stdc.h> using namespace std;template<typename T> class vector {public:typedef T value_type;typedef T* iterator;p…...

LLM建模了什么,为什么需要RAG
LLM近期研究是井喷式产出,如此多的文章该处何处下手,他们到底又在介绍些什么、解决什么问题呢?“为学日增,为道日损”,我们该如何从如此多的论文中找到可以“损之又损以至于无”的更本质道或者说是这个方向的核心模型。…...

为开发GPT-5,OpenAI向微软寻求新融资
11月14日,金融时报消息,OpenAI正在向微软寻求新一轮融资,用于开发超级智能向AGI(通用人工智能)迈进,包括最新模型GPT-5。 最近,OpenAI召开了首届开发者大会,推出了GPT-4 Turbo、自定…...

创邻科技亮相ISWC 2023,国际舞台见证知识图谱领域研究突破
近日,第22届国际语义网大会 ISWC 2023 在雅典希腊召开,通过线上线下的形式,聚集了全球的顶级研究人员、从业人员和行业专家,讨论、发展和塑造语义网和知识图谱技术的未来。创邻科技CEO张晨博士作为知识图谱行业专家受邀参会&#…...

开源博客项目Blog .NET Core源码学习(6:雪花算法)
Blog .NET项目中有多种数据类生成对象实例时需要唯一标识,一般做法要么使用GUID,也可以保存到数据库时使用数据库表的自增长ID,也可以自定义规则以确保产生不重复的唯一标识,而在Blog .NET项目中使用雪花算法生成唯一标识。 关…...