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返回的是已经执行完成的任务的执行结果,如果该任务执行异常,则抛出异常。

四. 模拟测试验证

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

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

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

相关文章

【管理咨询宝藏95】SRM采购平台建设内部培训方案

本报告首发于公号“管理咨询宝藏”&#xff0c;如需阅读完整版报告内容&#xff0c;请查阅公号“管理咨询宝藏”。 【管理咨询宝藏95】SRM采购平台建设内部培训方案 【格式】PDF版本 【关键词】SRM采购、制造型企业转型、数字化转型 【核心观点】 - 重点是建设一个适应战略采…

数据挖掘流程是怎样的?数据挖掘平台基本功能有哪些?

数据挖掘是从大量的、不完全的、有噪声的、模糊的、随机的数据中提取隐含在其中的、人们事先不知道的、但又是潜在有用的信息和知识的过程。 数据挖掘的流程是&#xff1a; 清晰地定义出业务问题&#xff0c;确定数据挖掘的目的。 数据准备: 数据准备包括&am…

机器学习 | 时间序列预测中的AR模型及应用

自回归模型&#xff0c;通常缩写为AR模型&#xff0c;是时间序列分析和预测中的一个基本概念。它们在金融、经济、气候科学等各个领域都有广泛的应用。在本文中&#xff0c;我们将探索自回归模型&#xff0c;它们如何工作&#xff0c;它们的类型和实际例子。 自回归模型 自回…

2024 GESP6级 编程第一题 游戏

题目描述 你有四个正整数 &#xff0c;并准备用它们玩一个简单的小游戏。 在一轮游戏操作中&#xff0c;你可以选择将 减去 &#xff0c;或是将 减去 。游戏将会进行多轮操作&#xff0c;直到当 时游戏结束。 你想知道游戏结束时有多少种不同的游戏操作序列。两种游戏操作…

虚拟机jvm下

jvm原理与实践 java程序的跨平台特性 jvm基本结构 JVM类加载流程和内存结构总览 类加载 加载阶段 类加载 验证阶段 类加载 准备阶段 类加载 解析阶段 类加载 初始化阶段 程序计数器 虚拟机栈&本地方法栈 栈帧操作 堆 方法区 永久代 元空间 垃圾回收 可触及性

python与java用途区别有哪些

区别&#xff1a; 1.Python比Java简单&#xff0c;学习成本低&#xff0c;开发效率高。 2.Java运行效率高于Python&#xff0c;尤其是纯Python开发的程序&#xff0c;效率极低。 3.Java相关资料多&#xff0c;尤其是中文资料。 4.Java版本比较稳定&#xff0c;Python2和3不…

笔记2:cifar10数据集获取及pytorch批量处理

&#xff08;1&#xff09;cifar10数据集预处理 CIFAR-10是一个广泛使用的图像数据集&#xff0c;它由10个类别的共60000张32x32彩色图像组成&#xff0c;每个类别有6000张图像。 CIFAR-10官网 以下为CIFAR-10数据集data_batch_*表示训练集数据&#xff0c;test_batch表示测试…

Ubuntu22.04下安装kafka_2.11-0.10.1.0并运行简单实例

目录 一、版本信息 二、安装Kafka 1.将Kafka安装包移到下载目录中 2.下载Spark并确保hadoop用户对Spark目录有操作权限 三、启动Kafka并测试Kafka是否正常工作 1.启动Kafka 2.测试Kafka是否正常工作 一、版本信息 虚拟机产品&#xff1a;VMware Workstation 17 Pro 虚…

C++从入门到精通---模版

文章目录 泛型编程函数模版模版参数的匹配原则类模版类模版的定义格式类模版的实例化 总结 泛型编程 泛型编程是一种编程范式&#xff0c;旨在实现通用性和灵活性。它允许在编写代码时使用参数化类型&#xff0c;而不是具体的类型&#xff0c;从而使代码更加灵活和可重用。 在…

Autoxjs 实践-Spring Boot 集成 WebSocket

概述 最近弄了福袋工具&#xff0c;由于工具运行中&#xff0c;不好查看福袋结果&#xff0c;所以我想将福袋工具运行数据返回到后台&#xff0c;做数据统计、之后工具会越来越多&#xff0c;就弄了个后台&#xff0c;方便管理。 实现效果 WebSocket&#xff1f; websocket是…

图像处理之SVD检测显示屏缺陷(C++)

图像处理之SVD检测显示屏缺陷&#xff08;C&#xff09; 文章目录 图像处理之SVD检测显示屏缺陷&#xff08;C&#xff09;前言一、SVD算法简介二、代码实现总结 前言 显示屏缺陷检测是机器视觉领域的一处较广泛的应用场景&#xff0c;显示屏主要有LCD和OLED&#xff0c;缺陷类…

本地连接服务器Jupyter【简略版】

首先需要在你的服务器激活conda虚拟环境&#xff1a; 进入虚拟环境后使用conda install jupyter命令安装jupyter&#xff1a; 安装成功后先不要着急打开&#xff0c;因为需要设置密码&#xff0c;使用jupyter notebook password命令输入自己进入jupyter的密码&#xff1a; …