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

news2024/11/24 6:43:56

在实际项目开发过程中,大部分程序的执行顺序都是按照代码编写的先后顺序,依次从上往下挨个执行的,但是对于统计或者批量操作数据时,是否有更好的方案呢?这时候就可以考虑使用多线程编程,异步并行执行多个任务,从而提升用户使用体验,发挥多核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返回的是已经执行完成的任务的执行结果,如果该任务执行异常,则抛出异常。

四. 模拟测试验证

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

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

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

相关文章

docker-compose安装es+kibana 8.12.2

小伙伴们&#xff0c;你们好&#xff0c;我是老寇&#xff0c;我又回来辣&#xff0c;几个月不见甚是想念啊&#xff01;&#xff01;&#xff01; 因云平台需要改造&#xff0c;es7升级为es8&#xff0c;所以记录一下&#xff0c;es8需要开启ssl认证&#xff0c;需要配置证书…

【3dmax笔记】027:配置修改器集、工具栏自定义与加载

文章目录 一、配置修改器集二、自定义工具栏三、加载工具栏 一、配置修改器集 可以把自己常用的修改命令放到右边框中的部分&#xff0c;便于自己的操作&#xff0c;省去了每次都要花半天时间找命令的尴尬。新建一个二维或者三维物体&#xff0c;点击修改面板&#xff0c;点击…

白盒测试:覆盖测试及测试用例设计

白盒测试&#xff1a;覆盖测试及测试用例设计 一、实验目的 1、掌握白盒测试的概念。 2、掌握逻辑覆盖法。 二、实验任务 某工资计算程序功能如下&#xff1a;若雇员月工作小时超过40小时&#xff0c;则超过部分按原小时工资的1.5倍的加班工资来计算。若雇员月工作小时超过…

1. C++入门:命名空间及输入输出

C相比C的变化 兼容C面向对象泛型C的不足的弥补 为什么要有命名空间 在C/C中&#xff0c;变量、函数和后面要学到的类都是大量存在的&#xff0c;这些变量、函数和类的名称将都存在于全局作用域中&#xff0c;可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地…

EMAP如何建数据源

新建数据源&#xff1a; EMAP底座的数据源&#xff0c;名称为“DB_EMAP_BIZ_BASE"&#xff0c;不可随意更改. 新建业务系统数据源&#xff0c;名称为”DB_STUDY_BIZ_BASE". 支持的数据库&#xff1a; 支持两种类型数据库&#xff1a;H2 和 oracle 新建H2数据源&am…

YOLOv9全网最新改进系列:YOLOv9融合HCF-NET网络中的PPA模块,红外小目标实验证明针对小目标的改进具有出色表现!

YOLOv9全网最新改进系列&#xff1a;YOLOv9融合HCF-NET网络中的PPA模块&#xff0c;红外小目标实验证明针对小目标的改进具有出色表现&#xff01; YOLOv9原文链接戳这里&#xff0c;原文全文翻译请关注B站Ai学术叫叫首er B站全文戳这里&#xff01; 详细的改进教程以及源码…

C语言贪吃蛇

注 &#xff1a;本文是基于链表实现贪吃蛇游戏 1.Win32 API 本篇文章中实现贪吃蛇会用到一些Win32 API的知识&#xff0c;接下来简单做下介绍 1.1 Win32 API Windows 这个多作业系统除了协调应用程序的执行、分配内存、管理资源之外&#xff0c; 它同时也是⼀个 很大的服务中…

vcenter7安装nsx

登录控制台 Get services

【噪声学习】噪声标签的鲁棒点云分割

Robust Point Cloud Segmentation with Noisy Annotations 事实上,与二维图像标注[1]、[2]相比,三维数据的干净标签更难获得。这主要是因为1)需要标注的点数通常非常庞大,例如在 ScanNetV2 [3] 中标注一个典型的室内场景时,需要标注百万量级的点数;2)标注过程本身更加复…

【4089】基于小程序实现的互动打卡系统

作者主页&#xff1a;Java码库 主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 技术选型 【后端】&#xff1a;Java 【框架】&#xff1a;spring…

Windows安装RabbitMQ教程(附安装包)

需要两个安装包 Erlang 安装包: https://download.csdn.net/download/Brevity6/89274663 (自己从官网下载也可以) RabbitMQ Windows 安装包&#xff1a; https://download.csdn.net/download/Brevity6/89274667 (自己从官网下载也可以) Erlang安装 Erlang安装傻瓜式下一…

Redis 之 布隆过滤器 与 布谷鸟过滤器

大家都知道,在计算机中IO一直是一个瓶颈,很多框架以及技术甚至硬件都是为了降低IO操作而生,今天聊一聊过滤器,先说一个场景: 我们业务后端涉及数据库,当请求消息查询某些信息时,可能先检查缓存中是否有相关信息,有的话返回,如果没有的话可能就要去数据库里面查询,这时候有一个…

新书速览|Rust编程与项目实战

掌握Rust编程基础和开发方法&#xff0c;实战网络编程、图像和游戏开发、数据分析项目 本书内容 Rust是一门系统编程语言&#xff0c;专注于安全&#xff0c;尤其是并发安全&#xff0c;它也是支持函数式、命令式以及泛型等编程范式的多范式语言。标准Rust在语法和性能上和标准…

小麦穗检测数据集VOC+YOLO格式6508张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;6508 标注数量(xml文件个数)&#xff1a;6508 标注数量(txt文件个数)&#xff1a;6508 标注…

IP定位技术在解决“薅羊毛”问题中扮演着关键角色

IP定位技术在解决被“薅羊毛”问题中扮演着关键角色。所谓“薅羊毛”&#xff0c;通常指的是在网络平台上&#xff0c;通过不正当手段获取优惠、奖励或利润的行为。这种行为不仅损害了平台的经济利益&#xff0c;也破坏了公平竞争的市场环境。IP定位技术通过提供IP地址的地理位…

多核DSP并行计算跨平台通信解决方案

并行计算的核心是计算节点以及节点间的通信与协调机制。OpenMP虽然给开发者提供了极易上手的增量式开发方式&#xff0c;但是OpenMP在与复杂架构的MCSDK结合后&#xff0c;工具与代码产生了大量不可调试的黑盒子&#xff0c;更是决定了它不能用于关键任务领域&#xff0c;如军工…

测评方式揭秘:自养号测评与真人测评的利与弊

在当今电商行业飞速发展的背景下&#xff0c;不少卖家为了提升产品销量和积累良好评价&#xff0c;采取了真人测评和自养号测评两种策略。然而&#xff0c;这两种测评方式的具体运作机制和效果差异&#xff0c;许多卖家可能并未深入了解。接下来&#xff0c;我们将深入挖掘真人…

Visual Studio C++ 2019进行安装

Visual Studio C 2019进行下载安装 链接&#xff1a;https://my.visualstudio.com/Downloads?qvisual%20studio%202017&wt.mc_idomsftvscom~older-downloads

流量分析利器arkime的学习之路(三)---结合Suricata攻击检测

1、基础 Arkime安装部分参考《流量分析利器arkime的学习之路&#xff08;一&#xff09;—安装部署》 在此基础上安装suricata软件并配置。 2、安装suricata yum install suricate 可能依赖的文件包括libyaml&#xff0c;PyYAML&#xff0c;这些可能在之前安装arkime或者其他…

在全志H616核桃派开发板上实现超声波传感器测距

前言​ 超声波传感器是一款测量距离的传感器。其原理是利用声波在遇到障碍物反射接收结合声波在空气中传播的速度计算的得出。在测量、避障小车&#xff0c;无人驾驶等领域都有相关应用。 实验目的​ 通过python编程实现超声波传感器测距。 实验讲解​ 下图是一款市面上常…