java多线程编码应用1——java多线程CompletableFuture使用技巧

在实际项目开发过程中,大部分程序的执行顺序都是按照代码编写的先后顺序,依次从上往下挨个执行的,但是对于统计或者批量操作数据时,是否有更好的方案呢?这时候就可以考虑使用多线程编程,异步并行执行多个任务,从而提升用户使用体验,发挥多核cpu的性能。

更多关于CompletableFuture的说明,请参看如下文章:

Java多线程之CompletableFuture_java completablefuture-CSDN博客

Java中的CompletableFuture原理与用法_java_脚本之家

以下文案是基于数据统计方案去设计编写的,希望可以对各位有所帮助。

一.CompletableFuture是什么

CompletableFuture是由Java8引入的,用于异步编程,异步通常意味着非阻塞,运行任务单独的线程,与主线程隔离。并且通过回调可以在主线程中得到异步任务的执行状态,是否完成和异常等信息。通过这种方式编程主线程不会被阻塞,不需要等到多个子线程执行完成,它可以并行执行其他任务。使用这种并行编程方式,可以极大的提高程序的执行和运行效率,提升用户使用体验等。

与Future对比:

  • CompletableFuture默认使用的是ForkJoinPool线程池;
  • CompletableFuture 是 Future API的扩展;
  • Future在实际使用过程中存在局限性,如不支持异步任务的编排组合,获取计算结果的get() 方法为阻塞调用;
  • CompletableFuture除了提供了更为好用和强大的 Future 特性之外,还提供了函数式编程、异步任务编排组合等扩展功能。

 二.如何创建CompletableFuture实例

1. supplyAsync()

通过该函数创建的CompletableFuture实例会异步执行当前传入的计算任务。在调用端,则可以通过get或join获取最终计算结果。

/**
* 有返回值的
* 如果不指定线程池,默认的构造方法使用ForkJoinPool
**/
ExecutorService executorService = Executors.newFixedThreadPool(4);
CompletableFuture<List<SysDept>> cfDeptList
                = CompletableFuture.supplyAsync(() -> {
            return remoteStationService.getAllStationInfo(0).getData();
        },executorService);
List<SysDept> join = cfDeptList.join();
2.runAsync()

与supplyAsync()不同的是,runAsync()传入的任务要求是Runnable类型的,所以没有返回值。因此,runAsync适合创建不需要返回值的计算任务。

//无返回值
CompletableFuture cf = CompletableFuture.runAsync(()->{
            getFireFightingData(params,resultAll);
        },fjp);
3.Future.get()和CompletableFuture.join()对比
  • 这两个方法都是阻塞方法,用于获取异步任务的结果。
  • Future.get()方法在获取异步任务结果时更具灵活性,因为它必须声明抛出异常且需要手动处理,同时它会阻塞线程调用。
  • CompletableFuture.join() 方法更适用于使用 ForkJoinPool 线程池执行任务的情况,它更方便用于不会阻塞 ForkJoinPool 线程池中的线程中。

三.CompletableFuture使用

        //仅展示部分关键代码        
        ForkJoinPool fjp = new ForkJoinPool(8);
        System.out.println("默认使用的线程为:" + Thread.currentThread().getName());
        CompletableFuture cf1 = CompletableFuture.runAsync(()->{
            System.out.println("cf1使用的线程为:" + Thread.currentThread().getName());
            //站数据
            List<StationDTO> stationAllVoList = staMapper.getAllStationVoList(null);
            Map<String, StationDTO> stationAllVoMap = null;
            if(CollectionUtils.isNotEmpty(stationAllVoList)){
                stationAllVoMap = stationAllVoList.stream().collect(Collectors.toMap(StationDTO::getStationName, Function.identity()));
            }else {
                stationAllVoMap = new HashMap<>();
            }
            resultAll.put("stationAllVoMap",stationAllVoMap);
        },fjp);
        System.out.println("cf1使用完之后的线程为:" + Thread.currentThread().getName());
        CompletableFuture cf2 = CompletableFuture.runAsync(()->{
            System.out.println("cf2使用的线程为:" + Thread.currentThread().getName());
            getSafetyCountData(params,resultAll);
        },fjp);
        CompletableFuture cf3 = CompletableFuture.runAsync(()->{
            System.out.println("cf3使用的线程为:" + Thread.currentThread().getName());
            getRectifyRateData(params,resultAll);
        },fjp);
        CompletableFuture cf4 = CompletableFuture.runAsync(()->{
            System.out.println("cf3使用的线程为:" + Thread.currentThread().getName());
            getAlarmARemindData(params,resultAll);
        },fjp);
        CompletableFuture.allOf(cf1,cf2,cf3,cf4).join();
        fjp.shutdown();

需要注意的点:

  • allOf()返回的CompletableFuture是多个任务都执行完成后才会执行,只要有一个任务执行异常,则返回的CompletableFuture执行get方法时会抛出异常,如果都是正常执行,则get返回null。
  • anyOf()返回的CompletableFuture是多个任务只要其中一个执行完成就会执行,其get返回的是已经执行完成的任务的执行结果,如果该任务执行异常,则抛出异常。

四. 模拟测试验证

经过测试, 多个子线程执行并不会影响主线程的继续执行,也不存在线程阻塞问题,与设计效果保持一致,非常值得借鉴学习。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Flink checkpoint 源码分析- Checkpoint snapshot 处理流程

背景 在上一篇博客中我们分析了代码中barrier的是如何流动改的。Flink checkpoint 源码分析- Checkpoint barrier 传递源码分析-CSDN博客 最后跟踪到了代码org.apache.flink.streaming.runtime.io.checkpointing.CheckpointedInputGate#handleEvent 现在我们接着跟踪相应代…

投资线上黄金是否属于外汇交易?探究黄金与外汇市场的关系

在金融市场中&#xff0c;线上黄金投资和外汇交易都是备受关注的领域。许多人可能会混淆这两者&#xff0c;认为投资线上黄金也是一种外汇交易。但实际上&#xff0c;尽管线上黄金和外汇交易有一些相似之处&#xff0c;但它们在本质上是不同的投资领域。本文将探讨投资线上黄金…

前端 Android App 上架详细流程 (Android App)

1、准备上架所需要的材料 先在需要上架的官方网站注册账号。提前把手机号&#xff0c;名字&#xff0c;身份证等等材料准备好&#xff0c;完成开发者实名认证&#xff1b;软著是必要的&#xff0c;提前准备好&#xff0c;软著申请时间比较长大概需要1-2周时间才能下来&#xf…

流畅的python-学习笔记_序列修改+散列+切片

vector第一版 reprlib.repr用于选取有限长度较长变量 vector第二版切片 注意切片还有indices属性&#xff0c;它可以入参一个序列长度&#xff0c;根据此序列长度&#xff0c;转化不规矩的start stop stride&#xff0c; vector第三版动态存取属性 obj.attra时&#xff0c;先…

构建 imx6ull sd 卡启动

1. 硬件环境 imx6ull 256MB tf 卡 512 MB 的 ddr&#xff1b; ubuntu 20.04&#xff1b; 芯片默认的启动方式是通过 LCD_DATA0 ~ LCD_DATA23&#xff1b;上下拉方式来确认的&#xff1b; 需要注意的上下拉是 BOOT_CFG1[7] BOOT_CFG1[6] BOOT_CFG1[5] 启动选择 和 BOOT_CF…

leetcode-矩阵最长递增路径-102

题目要求 思路 1.通过双循环去把每一个结点作为起始点进行统计&#xff0c;将返回的路径长度存放在res中&#xff0c;取最大的res的长度。 2.递归中需要的几个值&#xff0c;x和y当前结点的坐标&#xff0c;pre用于存储上一个结点的元素值&#xff0c;因为要求是路径上的元素是…

3D 交互展示该怎么做?

在博维数孪&#xff08;Bowell&#xff09;平台制作3D交互展示的流程相对简单&#xff0c;主要分为以下几个步骤&#xff1a; 1、准备3D模型&#xff1a;首先&#xff0c;你需要有一个3D模型。如果你有3D建模的经验&#xff0c;可以使用3ds Max或Blender等软件自行创建。如果没…

前后端分离项目中的一些疑惑

1、前后端分离项目&#xff0c;浏览器发起请求后&#xff0c;请求的是前端服务器还是后端服务器&#xff1f; 在前后端分离的项目中&#xff0c;当浏览器发起请求时&#xff0c;它首先会请求的是前端服务器。 前后端分离的工作流程大致如下&#xff1a; 用户在浏览器中输入网…

Echarts散点图的29个配置项,散点图可以随心所欲啦。

1-9 当使用 ECharts 绘制散点图时&#xff0c;可以配置以下一些常用的选项&#xff1a; 1. tooltip&#xff1a;配置提示框组件&#xff0c;用于显示鼠标悬停在散点上时的提示信息。 2. legend&#xff1a;配置图例组件&#xff0c;用于展示不同散点的标识和名称。 3. xAxis…

图数据库 之 Neo4j 与 AI 大模型的结合绘制知识图谱

引言 随着信息时代的到来&#xff0c;海量的文本数据成为了我们获取知识的重要来源。然而&#xff0c;如何从这些文本数据中提取出有用的信息&#xff0c;并将其以可视化的方式展示出来&#xff0c;一直是一个具有挑战性的问题。近年来&#xff0c;随着人工智能技术的发展&…

rust使用serde_json转换Value为rust中的数据类型

为了方便转换未知json数据&#xff0c;我们可以使用serde提供的value类型来进行转换&#xff0c;将json字符串转化为Value值&#xff0c;然后可以快速使用get方法来获取值&#xff1a; let json_str r#"{"name": "John","age": 30,"c…

科技控必看!让你轻松成为机器人领域达人

科技控们注意了&#xff01;你是不是经常对机器人技术充满无限的好奇&#xff0c;却又因为缺乏合适的渠道而难以深入了解和亲身体验呢&#xff1f;别担心&#xff0c;BFT机器人&#xff0c;正是你探索机器人世界的绝佳之地&#xff01; 在这里&#xff0c;你将发现一个充满惊喜…

政安晨:【Keras机器学习示例演绎】(三十九)—— 使用 FNet 进行文本分类

目录 简介 模型 设置 加载数据集 对数据进行标记 格式化数据集 建立模型 训练我们的模型 与变换器模型比较 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: TensorFlow与Keras机器学习实战 希望政安晨的博客能够对您有所裨益&…

Linux学习之高级IO

之前的内容我们基本掌握了基础IO&#xff0c;如套接字&#xff0c;文件描述符&#xff0c;重定向&#xff0c;缓冲区等知识都是文的基本认识&#xff0c;而高级IO则是指更加高效的IO。 对于应用层&#xff0c;在读写的时候&#xff0c;本质就是把数据写给OS&#xff0c;若一方…

1W 3KVDC 隔离 单输出 DC/DC 电源模块 ——TPF 系列

TPF系列提供输出稳压&#xff0c;精度高&#xff0c;对于输出电压有要求的场合特别适合&#xff0c;工业级环境温度&#xff0c;用于PCB安装的国际标准结构。此系列产品小巧&#xff0c;效率高&#xff0c;低输出纹波及提供3000V以上的直流电压隔离&#xff0c;封装有SIP和DIP可…

实测幻方新出的超强AI大模型,中文能力对比GPT4.0不落下风

目前从网上的消息来看&#xff0c;DeepSeek中文综合能力&#xff08;AlignBench&#xff09;开源模型中最强&#xff0c;与GPT-4-Turbo&#xff0c;文心4.0等闭源模型在评测中处于同一梯队。 话不多说&#xff0c;我们开测&#xff01; 1.首先我们来让他直接来一段逻辑推理【并…

Jetpack Compose三:主题和基础控件的使用

设置主题 与Android View的主题定义方式不同&#xff0c;Jetpack Compose中的主题由许多较低级别的结构体和相关API组成&#xff0c;它们包括颜色、排版和形状属性。 Theme.kt控制工程的主题&#xff0c;它是一个可组合的Compose函数 最后主题函数ComposeStudyTheme的相关设置…

安装Nox夜神模拟器关闭了HyperV后Docker运行不了怎么办?

1.背景 为了模拟真机&#xff0c;尝试安装了Nox夜神模拟器&#xff0c; 安装过程要求关闭Hyper-V。当时只是在程序安装卸载中关闭了系统服务。以为到时勾选上就好了。操作路径&#xff1a;控制面板\所有控制面板项\程序和功能\启用或关闭Windows功能\Hyper-V。 后来卸载掉了夜神…

D盘被格式化了能找回吗 d盘格式化了数据可以找回来吗

D盘作为电脑中重要的磁盘之一&#xff0c;很多用户都会将一些重要的数据保存在D盘。但在磁盘空间不足的情况下&#xff0c;或许有些用户会将其进行格式化&#xff0c;D盘被格式化了如何恢复数据&#xff1f; 如果是比较重要的数据&#xff0c;建议用户立即进行数据恢复操作&am…

Java-异常处理-定义三角形类Triangle和异常三角形IllegalTriangleException类 (1/2)

任意一个三角形&#xff0c;其任意两边之和大于第三边。当三角形的三条边不满足前述条件时&#xff0c;就表示发生了异常&#xff0c;将这种异常情况定义为IllegalTriangleException类。 自定义异常类IllegalTriangleException&#xff1a; 当三角形的三条边不满足条件&#x…