Java 入门指南:Java 并发编程 —— Fork/Join 框架 实现任务的拆分与合并
Fork/Join
Fork/Join 是Java并发编程中的一个框架,用于解决大型任务的并行执行问题。它于 Java 7中引入,旨在简化对多核处理器上可并行执行任务的开发。
Fork/Join 框架基于分治(divide and conquer)的设计思想。它将大型任务划分为更小的子任务(称为fork),这些子任务可以并行执行。一旦所有子任务都完成,它们的结果将被合并(称为join)以生成最终的结果。
优势之处
-
自动并行化:Fork/Join框架自动处理任务的并行执行,开发者只需要关注任务本身的逻辑。
-
高效利用多核:Fork/Join框架能够根据系统的处理器核心数自动调整线程数量,以充分利用多核处理器的计算能力。
-
易于实现复杂任务:通过递归拆分任务,可以轻松实现复杂的并行计算逻辑。
组成部分
1. ForkJoinPool
- ForkJoinPool 是Fork/Join框架的核心组件之一,它是一个特殊的线程池,专门用于执行Fork/Join任务。与普通的线程池相比,它提供了更高级别的任务管理和调度机制。
- ForkJoinPool 可以自动调整线程的数量,以适应当前系统可用的处理器核心数,从而最大化并行执行的效率。
2. ForkJoinTask
- ForkJoinTask 是所有Fork/Join任务的基类,它定义了任务的执行方式和生命周期。
- ForkJoinTask 可以通过
fork()方法提交给ForkJoinPool,这会导致任务被异步执行,而当前线程可以继续执行其他任务。 - 任务可以通过
join()方法等待其完成,并获取结果。
3. RecursiveAction
- RecursiveAction 是一个没有返回值的Fork/Join任务,通常用于执行计算密集型任务。
- 当任务足够小或者达到了某个阈值时,它会直接执行任务;否则,它会将任务分解为更小的子任务,并递归地调用
fork()方法提交给线程池。
4. RecursiveTask
- RecursiveTask 是一个有返回值的Fork/Join任务,通常用于执行计算密集型任务,并返回一个计算结果。
- 同样地,当任务足够小或者达到了某个阈值时,它会直接执行任务;否则,它会将任务分解为更小的子任务,并递归地调用
fork()方法提交给线程池。 - 任务的结果可以通过
compute()方法计算,并通过join()方法获取。
实现步骤
Fork/Join 框架的核心类是 java.util.concurrent.ForkJoinPool 。以下是使用 Fork/Join 模式的一般步骤:
-
定义一个继承自
RecursiveTask或RecursiveAction的任务类:RecursiveTask用于产生结果,RecursiveAction用于没有返回结果的任务。 -
在任务类中实现
compute()方法:在compute()方法中,定义任务的逻辑,包括将任务拆分为子任务的规则和处理任务的终止条件。 -
在需要执行 Fork/Join 任务的地方创建
ForkJoinPool对象:ForkJoinPool是处理任务的线程池。 -
创建任务实例,并调用
ForkJoinPool的invoke()或submit()方法提交任务:-
invoke()方法将任务提交并等待它的完成 -
submit()方法返回一个Future对象,使用它来获取任务的状态和结果。
-
-
处理任务的结果:一旦任务完成,从
Future对象中获取结果并进行必要的处理。
Fork/Join 框架适用于一些需要将大型任务划分为更小的可并行执行的子任务的情况。通过利用多核处理器的并行性,提高应用程序的性能和响应能力。
使用示例
以下是一个简单的Fork/Join框架的示例,展示了如何使用 ForkJoinPool 和 RecursiveTask 来计算数组中的元素之和:
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;public class ForkJoinSumCalculator extends RecursiveTask<Integer> {private final int threshold = 5; // 任务拆分的阈值private final int[] data;private final int start;private final int end;public ForkJoinSumCalculator(int[] data, int start, int end) {this.data = data;this.start = start;this.end = end;}@Overrideprotected Integer compute() {int length = end - start;if (length <= threshold) {// 直接计算return computeDirectly();} else {// 拆分任务int middle = start + length / 2;ForkJoinSumCalculator leftTask = new ForkJoinSumCalculator(data, start, middle);ForkJoinSumCalculator rightTask = new ForkJoinSumCalculator(data, middle, end);// 异步执行子任务leftTask.fork();rightTask.fork();// 合并子任务的结果return leftTask.join() + rightTask.join();}}private int computeDirectly() {int sum = 0;for (int i = start; i < end; i++) {sum += data[i];}return sum;}public static void main(String[] args) {int[] data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};ForkJoinPool pool = new ForkJoinPool();ForkJoinSumCalculator calculator = new ForkJoinSumCalculator(data, 0, data.length);int result = pool.invoke(calculator);System.out.println("数组的总和为: " + result);}
}
示例说明:
-
任务类定义:
ForkJoinSumCalculator继承自RecursiveTask<Integer>,它代表一个有返回值的Fork/Join任务。构造方法初始化了任务所需的数据范围。 -
任务执行方法 (
compute):compute方法定义了任务的执行逻辑。如果任务足够小(小于阈值),则直接计算并返回结果;否则,任务被拆分成两个子任务,并通过fork()方法提交给线程池。 -
直接计算方法 (
computeDirectly):computeDirectly方法实现了直接计算数据范围内元素之和的功能。 -
主程序 (
main):创建一个包含数字的数组,并实例化ForkJoinSumCalculator对象。创建一个ForkJoinPool实例,并通过invoke方法启动任务。获取计算结果并输出。
相关文章:
Java 入门指南:Java 并发编程 —— Fork/Join 框架 实现任务的拆分与合并
Fork/Join Fork/Join 是Java并发编程中的一个框架,用于解决大型任务的并行执行问题。它于 Java 7中引入,旨在简化对多核处理器上可并行执行任务的开发。 Fork/Join 框架基于分治(divide and conquer)的设计思想。它将大型任务划…...
token过期时间分平台(web和app)设置方法
token分平台设置方法 本文介绍了Spring下的登录和鉴权机制的主要方法以及 token认证的主要流程,并介绍在spring中web端和APP端设置不同token过期时间的实现方法。主要基于SpringBootspringSecurityJWT框架实现。 一、应用场景 同一系统的跨平台操作,基于…...
[000-01-008].Seata案例应用
业务说明:这里我们创建三个服务,一个订单服务,一个库存服务,一个账户服务。当用户下单时,会在订单服务中创建一个订单,然后通过远程调用库存服务来扣减下单商品的库存;再通过远程调用账户服务来…...
超详细!!!electron-vite-vue开发桌面应用之创建新窗口以及主进程和子进程的通信监听(十二)
云风网 云风笔记 云风知识库 一、新建打开窗口 1、在electron/main.ts中加入主进程打开窗口逻辑代码 import { ipcMain } from "electron"; ipcMain.handle("open-win", (_, arg) > {const childWindow new BrowserWindow({webPreferences: {preloa…...
java编辑器——IntelliJ IDEA
java编辑器有两种选择——IntelliJ IDEA和VsCode。其中IntelliJ IDEA现在是企业用的比较多的,是专门为java设计的,而VsCode则是通过插件来实现Java编辑的。 1.IntelliJ IDEA 官网下载链接:https://www.jetbrains.com/idea/ 注意选择社区版…...
经验笔记:SSL证书
SSL证书经验笔记 1. 什么是SSL证书? SSL(Secure Sockets Layer)证书是一种数字证书,用于在客户端(如浏览器)和服务器之间建立加密连接,以确保数据传输的安全性。随着互联网的发展,…...
设计模式之装饰器模式:让对象功能扩展更优雅的艺术
一、什么是装饰器模式 装饰器模式(Decorator Pattern)是一种结构型设计模式(Structural Pattern),它允许用户通过一种灵活的方式来动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比使用…...
Anchor Alignment Metric来优化目标检测的标签分配和损失函数。
文章目录 背景假设情况任务和目标TaskAligned方法的应用1. **计算Anchor Alignment Metric**2. **动态样本分配**3. **调整损失函数** 示例总结 背景 假设我们在进行目标检测任务,并且使用了YOLOv8模型。我们希望通过TaskAligned方法来优化Anchor与目标的匹配程度&…...
C++---由优先级队列认识仿函数
文章目录 一、优先级队列是什么? 二、如何使用优先级队列 1、优先级队列容器用法 2、为什么容器本身无序? 三、什么是仿函数? 1. 什么是仿函数? 2. 仿函数的优势 四、仿函数如何使用? 1、重载operator()函数 2、运用第…...
Client访问Server访问慢的原因
1. 网络层面的问题 网络延迟:客户端与服务器之间的地理距离较远(跨ISP、路径次优),导致高网络延迟(如高 RTT 值)。使用 ping 或 traceroute 工具可以帮助定位网络延迟的来源 - mtr: 结合了ping和traceroute功能&#…...
用RPC Performance Inspector 优化你的区块链
目录 什么是RPC? RPC Performance Inspector 是做什么的? 为什么需要这个工具? 如何使用它? 适合谁用? 如何使用? 什么是RPC? RPC Performance Inspector 是一个专门用于测试和分析RPC性能…...
linux如何查看内存条是ddr几代
在 Linux 系统中,可以通过以下几种方法查看内存条的类型和代数(如 DDR3、DDR4 等): 1. 使用 dmidecode 命令 dmidecode 是一个工具,它可以从系统的 DMI 表(也称为 SMBIOS 表)中提取硬件信息&a…...
LeetCode 3153.所有数对中数位差之和:计数
【LetMeFly】3153.所有数对中数位差之和:计数 力扣题目链接:https://leetcode.cn/problems/sum-of-digit-differences-of-all-pairs/ 车尔尼有一个数组 nums ,它只包含 正 整数,所有正整数的数位长度都 相同 。 两个整数的 数位…...
Spring Boot 整合 Sentinel 实现流量控制
在微服务架构中,流量控制是保障系统稳定性和高可用性的关键技术之一。阿里巴巴开源的 Sentinel 是一款面向分布式系统的流量防护组件,旨在从流量控制、熔断降级、系统负载保护等多个维度保障服务的稳定性。本文将详细介绍如何在 Spring Boot 项目中整合 …...
Elasticsearch倒排索引
什么是倒排索引 倒排索引(Inverted Index)是一种将文档中的每个单词映射到包含该单词的文档列表上的数据结构 倒排索引的构建过程 文档1: “我爱吃苹果” 文档2: “我爱吃香蕉” 文档3: “我喜欢苹果和香蕉” 文档分词:将文档中的文本内容…...
速盾:ddos常用防御方法是什么?
DDoS攻击是一种通过向网络资源发送大量请求或大流量数据来使其过载的攻击手段。为了应对这种攻击,常用的防御方法可以分为三个层次:流量清洗、服务器升级和高防CDN。 流量清洗是一种基础的防御手段,它通过过滤和识别恶意流量来阻止DDoS攻击。…...
二分算法入门(简单题)
习题1 704. 二分查找 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。 示例 1: 输入: nums [-1,0,3,5,9,12], targ…...
在使用React Hooks中,如何避免状态更新时的性能问题?
在React Hooks中避免状态更新时的性能问题,可以采取以下一些最佳实践: 避免不必要的状态更新: 使用React.memo、useMemo、和useCallback来避免组件或其子组件进行不必要的渲染。 使用useMemo: 对于基于状态或props的复杂计算&…...
Pytest插件pytest-selenium-让自动化测试更简洁
在现代Web应用的开发中,自动化测试成为确保网站质量的重要手段之一。而Pytest插件 pytest-selenium 则为开发者提供了简单而强大的工具,以便于使用Python进行Web应用的自动化测试。本文将深入介绍 pytest-selenium 插件的基本用法和实际案例,…...
视觉语言模型(VLMs)知多少?
最近这几年,自然语言处理和计算机视觉这两大领域真是突飞猛进,让机器不仅能看懂文字,还能理解图片。这两个领域的结合,催生了视觉语言模型,也就是Vision language models (VLMs) ,它们能同时处理视觉信息和…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)
RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发,后来由Pivotal Software Inc.(现为VMware子公司)接管。RabbitMQ 是一个开源的消息代理和队列服务器,用 Erlang 语言编写。广泛应用于各种分布…...
