CompletableFuture使用案例
优化代码时,除了@Async注解,项目中如何使用多线程异步调用?
举个例子,去餐厅吃饭的时候。先点餐,厨师做菜,在厨师做菜的时候打游戏,然后根据厨师做的菜的口味去买矿泉水还是可乐。这样,厨师做菜并没有阻塞你打游戏,并且还是能接收到厨师任务的结果。与2个任务同步进行相比缩短了时间。
CompletableFuture
FutureTask也行,但不用
- 工具类
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 说明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 | 主线程结束
- 测试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
- 测试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 | 番茄炒蛋 + 米饭做好了,小白开吃
- 测试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 | + 米饭 做好了,小白开吃
- 测试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 | 番茄炒蛋 + 米饭 做好了,小白开吃
相关文章:
CompletableFuture使用案例
优化代码时,除了Async注解,项目中如何使用多线程异步调用? 举个例子,去餐厅吃饭的时候。先点餐,厨师做菜,在厨师做菜的时候打游戏,然后根据厨师做的菜的口味去买矿泉水还是可乐。这样࿰…...
安卓使用so库
最近需要给小伙伴扫盲一下如何使用Android Studio 生成一个SO文件,网上找了很多都没有合适的样例,那只能自己来写一个了。 原先生成SO是一个很麻烦的事情,现在Android Studio帮忙做了很多的事情,基本只要管好自己的C代码即可。 …...

【介绍下LeetCode的使用方法】
🌈个人主页: 程序员不想敲代码啊 🏆CSDN优质创作者,CSDN实力新星,CSDN博客专家 👍点赞⭐评论⭐收藏 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共…...

重学java 30.API 1.String字符串
于是,虚度的光阴换来了模糊 —— 24.5.8 一、String基础知识以及创建 1.String介绍 1.概述 String类代表字符串 2.特点 a.Java程序中的所有字符串字面值(如“abc”)都作为此类的实例(对象)实现 凡是带双引号的,都是String的对象 String s "abc&q…...

【区块链】共识算法简介
共识算法简介 区块链三要素: 去中心化共识算法智能合约 共识算法作为区块链三大核心技术之一,其重要性不言而喻。今天就来简单介绍共识算法的基本知识。 最简单的解释,共识算法就是要让所有节点达成共识,保证少数服从多数&#x…...

Qt---day2-信号与槽
1、思维导图 2、 拖拽式 源文件 #include "mywidget.h" #include "ui_mywidget.h" MyWidget::MyWidget(QWidget *parent) : QWidget(parent) , ui(new Ui::MyWidget) { ui->setupUi(this); //按钮2 this->btn2new QPushButton("按钮2",th…...

Python中设计注册登录代码
import hashlib import json import os import sys # user interface 用户是界面 UI """ 用户登录系统 1.注册 2.登陆 0.退出 """ # 读取users.bin def load(path): return json.load(open(path, "rt")) # 保存user.bin def save(dic…...

AI伦理和安全风险管理终极指南
人工智能(AI)正在迅速改变各个领域的软件开发和部署。驱动这一转变的两个关键群体为人工智能开发者和人工智能集成商。开发人员处于创建基础人工智能技术的最前沿,包括生成式人工智能(GenAI)模型、自然语言处理&#x…...
golang testing使用
testing包服务于自动化测试 基本测试 Table Drvien Test 基于表的测试通过表形式进行测试每种情况的输入和期望输出,从而测试程序的正确性 func TestFib(t *testing.T) {var fibTests []struct {in int // inputexpected int // expected result}{{1, 1}…...
在Excel中使用正则提取单元格内容
在办公自动化的浪潮中,Excel 作为数据处理的利器,一直在不断进化。最近,我注意到了不坑盒子Office插件一个非常实用的功能更新——bk_regex_string 公式。这个功能对于我们这些日常需要处理大量文本和数据的办公人员来说,无疑是一…...

SQL查询语句(二)逻辑运算关键字
上一篇文章中我们提到了条件查询除了一些简单的数学符号之外,还有一些用于条件判断的关键字,如逻辑判断 关键字AND,OR,NOT和范围查找关键字BETWEEN,IN等;下面我们来介绍一些这些关键字的用法以及他们所表达的含义。 目录 逻辑运算关键字 AND…...
矿山机械自动化中的激光雷达技术探索
在矿山机械自动化技术的快速发展中,激光雷达技术作为其关键组成部分,正发挥着越来越重要的作用。本文将深入探讨激光雷达在矿山机械自动化中的应用,以及其所面临的挑战与未来发展趋势。 一、激光雷达在矿山机械自动化中的应用 激光雷达技术…...

MOSFET场效应管栅极驱动电流的计算
MOSFET驱动 MOSFET场效应管是电压驱动器件,输入有电容,因此为可靠驱动MOSFET,栅极需要施加较大的驱动电流。 功率MOSFET开关模型 该模型显示了影响开关性能的最重要的寄生器件。 栅极所需驱动电流计算公式 一个很重要的参数是计算栅极驱…...
Python 爬虫:Spring Boot 反爬虫的成功案例
前言 在当今数字化时代,网络数据成为了信息获取和分析的重要来源之一。然而,随着网络数据的广泛应用,爬虫技术也逐渐成为了互联网行业的热门话题。爬虫技术的应用不仅可以帮助企业获取有价值的信息,还可以用于数据分析、市场研究…...

计算机毕业设计Python+Vue.js天气预测系统 中国气象质量采集与可视化 天气数据分析 天气可视化 天气大数据 天气爬虫 大数据毕业设计
摘要 随着科技技术的不断发展,人民物质生活质量不断提高,我们越来越关注身边的气象、空气等地理环境。对于普通居民我们会选择合适的气象进行出游,提高精神层面的生活质量;对于企业会关注气象变换状况,来定制相关的生产…...

【busybox记录】【shell指令】tr
目录 内容来源: 【GUN】【tr】指令介绍 【busybox】【tr】指令介绍 【linux】【tr】指令介绍 使用示例: 转换字符 - 默认 转换字符 - 不翻译指定字符数组 此指令目前接触少,用得少,把精力放到其他常用指令上 常用组合指令…...

Mac虚拟机软件哪个好用 mac虚拟机parallels desktop有什么用 Mac装虚拟机的利与弊 mac装虚拟机对电脑有损害吗
随着多系统使用需求的升温,虚拟机的使用也变得越来越普遍。虚拟机可以用于创建各种不同的系统,并按照要求设定所需的系统环境。另外,虚拟机在Mac电脑的跨系统使用以及测试软件系统兼容性等领域应用也越来越广泛。 一、Mac系统和虚拟机的区别 …...

Type-C转音频(USB2.0数据传输)+PD充电芯片乐得瑞LDR6500/LDR6023
LDR6500 USB-C DRP 接口 USB PD 通信芯片概述 Type-C转音频(USB2.0数据传输)PD充电芯片乐得瑞LDR6500LDR6500是乐得瑞科技针对USB Type-C标准中的Bridge设备而开发的USB-C DRP(Dual Role Port,双角色端口)接口USB PD(Power Deliv…...

【busybox记录】【shell指令】expand
目录 内容来源: 【GUN】【expand】指令介绍 【busybox】【expand】指令介绍 【linux】【expand】指令介绍 使用示例: 把制表符转化为空格 - 默认输出 把制表符转化为空格 - 修改制表符转空格的个数 把制表符转化为空格 - 修改制表符转空格的个数…...
软件测试—— 接口测试之通讯流程相关概念
通讯流程 1、协议 通讯规则 2、HTTP协议 协议的一种 3、接口规范文档 如何发请求的要求文档,获取什么响应内容的说明文档(相当于菜单)...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...

srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...

Module Federation 和 Native Federation 的比较
前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...

【分享】推荐一些办公小工具
1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由:大部分的转换软件需要收费,要么功能不齐全,而开会员又用不了几次浪费钱,借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...

并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台
淘宝扭蛋机小程序系统的开发,旨在打造一个互动性强的购物平台,让用户在购物的同时,能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机,实现旋转、抽拉等动作,增…...