CompletableFuture使用案例

优化代码时,除了@Async注解,项目中如何使用多线程异步调用?
举个例子,去餐厅吃饭的时候。先点餐,厨师做菜,在厨师做菜的时候打游戏,然后根据厨师做的菜的口味去买矿泉水还是可乐。这样,厨师做菜并没有阻塞你打游戏,并且还是能接收到厨师任务的结果。与2个任务同步进行相比缩短了时间。

CompletableFuture

FutureTask也行,但不用

  1. 工具类
public class SmallTools {public static void sleepMillis(long millis){try {Thread.sleep(millis);}catch (InterruptedException exception){exception.printStackTrace();}}public static void printTimeAndThread(String tag){String result = new StringJoiner("\t|\t").add(String.valueOf(System.currentTimeMillis())).add(String.valueOf(Thread.currentThread().getId())).add(Thread.currentThread().getName()).add(tag).toString();System.out.println(result);}
}
  1. 测试1 说明CompletableFuture.supplyAsync会立即在后台线程池中异步执行 lambda 表达式,不需要显式调用。
public class Main {public static void main(String[] args) {SmallTools.printTimeAndThread("小白进入餐厅");SmallTools.printTimeAndThread("小白点了 番茄炒蛋 + 一碗米饭");CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> {SmallTools.printTimeAndThread("厨师炒菜");SmallTools.sleepMillis(4000);SmallTools.printTimeAndThread("cf1线程结束");return "番茄炒蛋";});SmallTools.printTimeAndThread("小白开始打王者");SmallTools.sleepMillis(5000);SmallTools.printTimeAndThread("主线程结束");}
}
------
1715099888262	|	1	|	main	|	小白进入餐厅
1715099888262	|	1	|	main	|	小白点了 番茄炒蛋 + 一碗米饭
1715099888279	|	1	|	main	|	小白开始打王者
1715099888279	|	9	|	ForkJoinPool.commonPool-worker-9	|	厨师炒菜
1715099892285	|	9	|	ForkJoinPool.commonPool-worker-9	|	cf1线程结束
1715099893282	|	1	|	main	|	主线程结束
  1. 测试2 同时开启多个异步调用
public class Main {public static void main(String[] args) {SmallTools.printTimeAndThread("小白进入餐厅");SmallTools.printTimeAndThread("小白点了 番茄炒蛋 + 一碗米饭");CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> {SmallTools.printTimeAndThread("厨师炒菜");SmallTools.sleepMillis(4000);SmallTools.printTimeAndThread("cf1线程结束");return "番茄炒蛋";});CompletableFuture<String> cf2 = CompletableFuture.supplyAsync(() -> {SmallTools.printTimeAndThread("服务员打饭");SmallTools.sleepMillis(4000);SmallTools.printTimeAndThread("cf2线程结束");return "饭";});SmallTools.printTimeAndThread("小白开始打王者");SmallTools.sleepMillis(5000);SmallTools.printTimeAndThread("主线程结束");}
}
------
1715100175308	|	1	|	main	|	小白进入餐厅
1715100175308	|	1	|	main	|	小白点了 番茄炒蛋 + 一碗米饭
1715100175325	|	1	|	main	|	小白开始打王者
1715100175326	|	9	|	ForkJoinPool.commonPool-worker-9	|	厨师炒菜
1715100175326	|	10	|	ForkJoinPool.commonPool-worker-2	|	服务员打饭 //睡了4秒
1715100179338	|	9	|	ForkJoinPool.commonPool-worker-9	|	cf1线程结束
1715100179338	|	10	|	ForkJoinPool.commonPool-worker-2	|	cf2线程结束
1715100180331	|	1	|	main	|	主线程结束Process finished with exit code 0
  1. 测试3 等待异步调用的结果,根据结果再处理逻辑
public class Main {public static void main(String[] args) {SmallTools.printTimeAndThread("小白进入餐厅");SmallTools.printTimeAndThread("小白点了 番茄炒蛋 + 一碗米饭");CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> {SmallTools.printTimeAndThread("厨师炒菜");SmallTools.sleepMillis(4000);SmallTools.printTimeAndThread("厨师打饭");SmallTools.sleepMillis(2000);return "番茄炒蛋 + 米饭";});SmallTools.printTimeAndThread("小白开始打王者");SmallTools.printTimeAndThread(String.format("%s做好了,小白开吃",cf1.join()));}
}----结果
1715098991592	|	1	|	main	|	小白进入餐厅
1715098991592	|	1	|	main	|	小白点了 番茄炒蛋 + 一碗米饭
1715098991608	|	1	|	main	|	小白开始打王者
1715098991610	|	9	|	ForkJoinPool.commonPool-worker-9	|	厨师炒菜 //睡了4秒
1715098995625	|	9	|	ForkJoinPool.commonPool-worker-9	|	厨师打饭 //睡了2s
1715098997637	|	1	|	main	|	番茄炒蛋 + 米饭做好了,小白开吃
  1. 测试4 链式调用,开启2个线程,第二个线程等待第一个线程结束后在异步调用
public class Main {public static void main(String[] args) {SmallTools.printTimeAndThread("小白进入餐厅");SmallTools.printTimeAndThread("小白点了 番茄炒蛋 + 一碗米饭");CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> {SmallTools.printTimeAndThread("厨师炒菜");SmallTools.sleepMillis(4000);return "番茄炒蛋";}).thenCompose(dish -> CompletableFuture.supplyAsync(()->{SmallTools.printTimeAndThread("厨师打饭");SmallTools.sleepMillis(2000);return " + 米饭";}));SmallTools.printTimeAndThread("小白开始打王者");SmallTools.printTimeAndThread(String.format("%s 做好了,小白开吃",cf1.join()));}
}
------
1715100509306	|	1	|	main	|	小白进入餐厅
1715100509306	|	1	|	main	|	小白点了 番茄炒蛋 + 一碗米饭
1715100509323	|	9	|	ForkJoinPool.commonPool-worker-9	|	厨师炒菜
1715100509323	|	1	|	main	|	小白开始打王者 //等待4秒
1715100513328	|	9	|	ForkJoinPool.commonPool-worker-9	|	厨师打饭 //等待2秒
1715100515342	|	1	|	main	|	 + 米饭 做好了,小白开吃
  1. 测试5 同时开启2个异步调用,其实和测试2没什么区别,代码好看点
public class Main {public static void main(String[] args) {SmallTools.printTimeAndThread("小白进入餐厅");SmallTools.printTimeAndThread("小白点了 番茄炒蛋 + 一碗米饭");CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> {SmallTools.printTimeAndThread("厨师炒菜");SmallTools.sleepMillis(4000);return "番茄炒蛋";}).thenCombine(CompletableFuture.supplyAsync(() -> {SmallTools.printTimeAndThread("服务员蒸饭");SmallTools.sleepMillis(4000);return "米饭";}),(dish,rice) -> {SmallTools.printTimeAndThread("服务员打饭");return dish + " + " +rice;});SmallTools.printTimeAndThread("小白开始打王者");SmallTools.printTimeAndThread(String.format("%s 做好了,小白开吃",cf1.join()));}
}
------
1715101146820	|	1	|	main	|	小白进入餐厅
1715101146820	|	1	|	main	|	小白点了 番茄炒蛋 + 一碗米饭
1715101146837	|	9	|	ForkJoinPool.commonPool-worker-9	|	厨师炒菜
1715101146837	|	10	|	ForkJoinPool.commonPool-worker-2	|	服务员蒸饭
1715101146838	|	1	|	main	|	小白开始打王者 //睡了4秒
1715101150852	|	9	|	ForkJoinPool.commonPool-worker-9	|	服务员打饭
1715101150858	|	1	|	main	|	番茄炒蛋 + 米饭 做好了,小白开吃

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

区块链 | NFT 相关论文:Preventing Content Cloning in NFT Collections(三)

&#x1f436;原文&#xff1a; Preventing Content Cloning in NFT Collections &#x1f436;写在前面&#xff1a; 这是一篇 2023 年的 CCF-C 类&#xff0c;本博客只记录其中提出的方法。 F C o l l N F T \mathbf{F_{CollNFT}} FCollNFT​ and Blockchains with Native S…

SpringBoot2 仿B站高性能前端+后端项目(wanjie)

SpringBoot2 仿B站高性能前端后端项目(完结) Spring Boot 2 仿B站高性能前端后端项目&#xff1a;打造高效、稳定、可扩展的应用 在当今的互联网时期&#xff0c;网站的性能、稳定性和可扩展性成为了权衡一个项目胜利与否的关键要素。本文将引见如何运用 Spring Boot 2 构建一…

智启算力平台基本操作

智启算力平台 智启算力平台路径搭载数据集搭载镜像配置 智启算力平台 开发文档 帮助文档 - OpenI - 启智AI开源社区 路径搭载 OpenIOSSG/promote: 启智AI协作平台首页推荐组织及推荐项目申请。 - notice/Other_notes/SDKGetPath.md at master - promote - OpenI - 启智AI开…

数据结构-线性表-应用题-2.2-11

1)算法的基本设计思想&#xff1a; 分别求两个升序序列的中位数a,b 若ab&#xff0c;则a或b即为所求中位数 若a<b&#xff0c;则舍弃A中较小的一半&#xff08;中位数偏小&#xff0c;往后面找&#xff09;&#xff0c;同时舍弃序列B中较大的一半&#xff0c;两次舍弃长度…

【Leetcode每日一题】 穷举vs暴搜vs深搜vs回溯vs剪枝_全排列 - 子集(解法2)(难度⭐⭐)(72)

1. 题目解析 题目链接&#xff1a;78. 子集 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 2.算法原理 为了生成一个给定数组 nums 的所有子集&#xff0c;我们可以利用一种称为回溯&#xff08;backtracking&#xff09;的算法…

pytest(二):关于pytest自动化脚本编写中,初始化方式setup_class与fixture的对比

一、自动化脚本实例对比 下面是一条用例,使用pytest框架,放在一个类中,两种实现方式: 1.1 setup_class初始化方式 1. 优点: 代码结构清晰,setup_class 和 teardown_class 看起来像传统的类级别的 setup 和 teardown 方法。2. 缺点: 使用 autouse=True 的 fixture 作为…

Mac 链接 HP 136w 打印机步骤

打开 WI-FI 【1】打开打印机左下角Wi-Fi网络设计【或者点击…按钮进入WI-FI菜单】&#xff0c;找到NetWork选项OK进入&#xff1b; 【2】设置WI-FI选项&#xff1a;在菜单内找到Wi-Fi选项OK进入&#xff1b; 【3】在菜单内找到Wi-Fi Direct选项OK进入&#xff1b; 【4】在菜单…

java:File类概述和构造方法

一、File类概述和构造方法 1.File类的概述 File&#xff1a;它是文件和目录路径名的抽象表示 文件和目录是可以通过File封装成对象的对File而言&#xff0c;其封装并不是一个真正存在的文件&#xff0c;仅仅是一个路径名而已。它可以是存在的&#xff0c;也可以是不存在的。…

瑞友天翼应用虚拟化系统SQL注入致远程代码执行漏洞复现

0x01 产品简介 瑞友天翼应用虚拟化系统是西安瑞友信息技术资讯有限公司研发的具有自主知识产权,基于服务器计算架构的应用虚拟化平台。它将用户各种应用软件集中部署在瑞友天翼服务器(群)上,客户端通过WEB即可快速安全的访问经服务器上授权的应用软件,实现集中应用、远程接…

人工智能-2024期中考试

前言 人工智能期中考试&#xff0c;认真准备了但是没考好&#xff0c;结果中游偏下水平。 第4题没拿分 &#xff08;遗传算法&#xff1a;知识点在课堂上一笔带过没有细讲&#xff0c;轮盘赌算法在书本上没有提到&#xff0c;考试的时候也没讲清楚&#xff0c;只能靠猜&…

Python网络协议socket

01 协议基础 01 网络协议 协议&#xff1a;一种规则 网络协议&#xff1a;网络规则&#xff0c;一种在网络通信中的数据包的数据规则 02 TCP/IP协议 osi模型 tcp/ip协议 03 tcp协议 TCP协议提供了一种端到端的、基于连接的、可靠的通信服务。 三次握手 创建连接 四次挥手…

华为:三层交换机与路由器连通上网实验

三层交换机是一种网络交换机&#xff0c;可以实现基于IP地址的高效数据转发和路由功能&#xff0c;通常用于大型企业、数据中心和校园网络等场景。此外&#xff0c;三层交换机还支持多种路由协议&#xff08;如OSPF、BGP等&#xff09;&#xff0c;以实现更为复杂的网络拓扑结构…

深度学习之基于Matlab卷积神经网络验证码识别系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景 随着互联网的发展&#xff0c;验证码作为一种常用的安全验证手段&#xff0c;被广泛应用于各种网站和…

W801学习笔记二十一:英语背单词学习应用——上

英语背单词是比较常见的学习APP&#xff0c;参考唐诗宋词应用&#xff0c;本章做一个类似的应用。 一、单词数据清洗及格式转换 诗词数据的获取渠道很多&#xff0c;一般可以按照年级来分文件。如一到九年级&#xff0c;四六级&#xff0c;雅思等等。 1、先从网上某某地方下载…

python+flask+ldap3搭建简易版IDaaS系统(前端站点)

Python工具开源专栏 Py0006 pythonflaskldap3搭建简易版IDaaS系统&#xff08;前端站点&#xff09; Python工具开源专栏前言目录结构前端网站的部分演示首页查询数据数据同步数据关联查询系统日志 完整代码已在GitHub上开源 前言 pythonflaskldap3搭建简易版IDaaS系统的前端站…

redis分片java实践、redis哨兵机制实现、redis集群搭建

redis分片java实践 linux安装redishttps://mp.csdn.net/mp_blog/creation/editor/134864302复制redis.conf配置文件成redis1.conf、redis2.conf、redis3.conf 修改redis的端口信息和存pid文件的路径。存pid文件的路径只要不同就行了&#xff0c;没什么特别要求。 指定配置文件…

《Fundamentals of Power Electronics》——示例:Buck-Boost转换器模型变为正则形式

为了说明正则电路模型推导的步骤&#xff0c;让我们将buck-boost转换器的等效电路操作成规范形式。buck-boost转换器的一个小信号交流等效电路如下图所示。 为了将上图所示网络转换成正则形式&#xff0c;需要将所有独立源d(t)转换到左侧&#xff0c;而将所有电感转换到右侧与变…

【Qt QML】ComboBox组件

ComboBox 是一个组合的按钮和弹出列表。它提供了一种以最小的屏幕空间呈现选项列表给用户的方式。ComboBox 使用数据模型填充。数据模型通常是一个 JavaScript 数组、一个 ListModel 或一个整数&#xff0c;但也支持其他类型的数据模型。 下面是一个简单的使用方式。 import …

机器学习——5.案例: 乳腺癌预测

案例目的 通过已标注的数据&#xff0c;训练出模型来预测患者是否有患乳腺癌。 该问题属于二分类问题&#xff0c;所以可以使用Sigmoid激活函数&#xff0c;损失用BCE函数 代码逻辑步骤 读取数据训练集与测试集拆分数据标准化数据转化为Pytorch张量label维度转换定义模型定…

汽车 - 什么是车轮抱死

车轮抱死分为两种情况&#xff0c;一种是车辆故障层面&#xff0c;另一种是驾驶过程中的物理现象。我们先来说最通俗的刹车车轮抱死吧。 刹车制动车轮抱死 车轮停止轴向转动就是抱死&#xff0c;有速度的情况下抱死车轮&#xff0c;如果车辆的惯性动能大于轮胎抓地力&#xff0…