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) ,它们能同时处理视觉信息和…...

python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...

让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...

自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...

抽象类和接口(全)
一、抽象类 1.概念:如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象,这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法,包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中,⼀个类如果被 abs…...
k8s从入门到放弃之HPA控制器
k8s从入门到放弃之HPA控制器 Kubernetes中的Horizontal Pod Autoscaler (HPA)控制器是一种用于自动扩展部署、副本集或复制控制器中Pod数量的机制。它可以根据观察到的CPU利用率(或其他自定义指标)来调整这些对象的规模,从而帮助应用程序在负…...

Vue3 PC端 UI组件库我更推荐Naive UI
一、Vue3生态现状与UI库选择的重要性 随着Vue3的稳定发布和Composition API的广泛采用,前端开发者面临着UI组件库的重新选择。一个好的UI库不仅能提升开发效率,还能确保项目的长期可维护性。本文将对比三大主流Vue3 UI库(Naive UI、Element …...
大数据治理的常见方式
大数据治理的常见方式 大数据治理是确保数据质量、安全性和可用性的系统性方法,以下是几种常见的治理方式: 1. 数据质量管理 核心方法: 数据校验:建立数据校验规则(格式、范围、一致性等)数据清洗&…...