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、接口规范文档 如何发请求的要求文档,获取什么响应内容的说明文档(相当于菜单)...
SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...
排序算法总结(C++)
目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指:同样大小的样本 **(同样大小的数据)**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...
GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...
从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障
关键领域软件测试的"安全密码":Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力,从金融交易到交通管控,这些关乎国计民生的关键领域…...
