java中的fork、join是什么?这个fork和我们常见到的如“fork一个进程去执行xxx”是一回事么?

Java Fork/Join框架深度解析 Fork/Join框架是Java 7引入的并行任务执行框架,基于“分而治之”思想,适用于可递归分解的计算密集型任务。其核心组件包括ForkJoinPool、ForkJoinTask及其子类RecursiveAction和RecursiveTask。框架通过工作窃取算法提高CPU利用率,减少线程竞争,实现高效任务调度。使用Fork/Join框架时,需定义任务、实现compute方法、创建线程池并提交任务。优化策略包括合理设置阈值、选择任务分割策略和避免阻塞操作。Fork/Join框架特别适合多核处理器环境,能 阅读详情

首先,说一下fork:

  • 操作系统中的 Fork:

        在Unix-like的操作系统中,fork()指的是一个系统调用,用于创建一个与当前进程几乎完全相同的新进程。新进程(子进程)是原进程(父进程)的副本,包括父进程的代码、数据、堆、栈等内容。子进程随后可以执行不同的程序(通过exec()系统调用)或继续执行与父进程相同的程序。

  • Java 中的 Fork (与 ForkJoinPool 和 ForkJoinTask 相关):

        在Java中,fork方法是ForkJoinTask类的一个方法,用于将当前任务拆分为子任务,并将这些子任务提交到ForkJoinPool中执行。这里的“fork”是为了利用多核处理器并行执行任务的机制,旨在提高性能。

总结:
        操作系统中的fork用于创建新的进程,该进程是当前进程的副本。
        Java中的fork(与ForkJoinPool和ForkJoinTask相关)用于将任务拆分为子任务,以便在并行环境中执行。

        可见,Java的fork与操作系统级别的fork在目的和用法上完全不同。Java的fork用于任务拆分和并行处理,而操作系统的fork用于创建新的进程(如在Redis中bgsave、rdb等实际都是通过系统调用fork一个子进程去执行一些耗时的操作,避免了主进程的阻塞执行)。

接下来,重点学习下java中的fork/join。

java中的fork/join,是自java7开始引入的一个框架,是用于并行编程的API,位于JUC(java.util.cocurrent)包中。

fork:用于把任务拆分为子任务,并把这些子任务提交到ForkJoinPool中去执行;

join:等待任务执行完成,并获取其结果(如果有的话,分两类:RecursiveAction和RecursiveTask,后面会介绍)

(到这一步,我们如果遇到一些开源项目中用到了fork/join,就可以简单理解为:fork-是把一个大任务拆分成多个子任务去执行了,join-是等待任务执行完成并获取最终结果,有点类似MapReduce的原理)

接下来,再细展开说说。

java中的fork/join,通常与ForkJoinPool和ForkJoinTask类相关,在java7中被引入用于支持并行编程。

ForkJoinPool:

        ForkJoinPool 是一个可以执行 ForkJoinTask 的线程池。它使用工作窃取(work-stealing)算法来有效地利用线程,当一个线程完成其任务时,它会从其他线程的队列中窃取任务来执行。

        

        从类图中可以看出,ForkJoinPool继承自AbstractExecutorService,重写了线程池的一些方法(execute、submit等)。

ForkJoinTask:

        ForkJoinTask 是一个可以拆分为子任务的抽象任务。我们通常不直接继承它,它有两个主要的子类:RecursiveAction(用于没有返回结果的任务)和 RecursiveTask(用于有返回结果的任务)。

        

示例代码:

下面是一个简单的例子,通过使用ForkJoinPool和ForkJoinTask来计算一个大数组的总和。

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

public class ForkJoinSumCalculator extends RecursiveTask<Long> {

    private static final int THRESHOLD = 1000; // 阈值,当数组长度小于这个值时不再拆分
    private final long[] numbers;
    private final int start;
    private final int end;

    public ForkJoinSumCalculator(long[] numbers) {
        this(numbers, 0, numbers.length);
    }

    private ForkJoinSumCalculator(long[] numbers, int start, int end) {
        this.numbers = numbers;
        this.start = start;
        this.end = end;
    }

    @Override
    protected Long compute() {
        int length = end - start;
        if (length <= THRESHOLD) {
            return computeDirectly();
        } else {
            int mid = (start + end) >>> 1; // 无符号右移,计算中点
            ForkJoinSumCalculator leftTask = new ForkJoinSumCalculator(numbers, start, mid);
            ForkJoinSumCalculator rightTask = new ForkJoinSumCalculator(numbers, mid, end);
            leftTask.fork(); // 拆分左侧任务
            Long rightResult = rightTask.compute(); // 直接计算右侧任务(因为compute会调用fork和join)
            Long leftResult = leftTask.join(); // 等待左侧任务完成并获取结果
            return leftResult + rightResult; // 合并结果
        }
    }

    private long computeDirectly() {
        long sum = 0;
        for (int i = start; i < end; i++) {
            sum += numbers[i];
        }
        return sum;
    }

    public static void main(String[] args) {
        long[] numbers = new long[1000000]; // 创建一个包含100万个元素的数组
        for (int i = 0; i < numbers.length; i++) {
            numbers[i] = i;
        }
        ForkJoinPool pool = new ForkJoinPool(); // 创建一个ForkJoinPool
        ForkJoinSumCalculator task = new ForkJoinSumCalculator(numbers); // 创建一个任务
        Long result = pool.invoke(task); // 提交任务并等待结果
        System.out.println("Sum: " + result); // 输出结果
    }
}

在这个例子中,ForkJoinSumCalculator 类继承自 RecursiveTask<Long>,它负责计算一个长整型数组的总和。当数组的长度超过某个阈值时,任务会被拆分(fork)为两个子任务,每个子任务计算数组的一部分的总和。然后,这些子任务的结果会被合并起来(join)得到最终的总和。

工作窃取(work-stealing)算法:

(让文心一言帮忙解释一下吧,非度厂员工,不是宣传,纯粹为了方便)

(不得不说,解释的还是很不错的,直观明了)

好了,就这样吧,大概够用了。

Java 并发容器和框架Fork/Join详解 普通任务:runnable接口,Callable接口等实现类ForkJoinTask子类:CountedCompleter、RecursiveAction、RecursiveTask是其进一步实现封装的抽象类;用户选取上述类自行实现即可。 阅读详情

相关推荐

Sharding-JDBC 系列专题 - 第九篇:高可用性与集群管理

高可用性是指系统在面对故障(如数据库宕机、网络中断)时,能够快速恢复并继续提供服务。Sharding-JDBC 和 Sharding-Proxy 提供了多种机制支持高可用性,同时需要结合底层数据库的高可用方案(如 MySQL 主从复制、MHA)来实现。高可用性和集群管理是 Sharding-JDBC 和 Sharding-Proxy 在生产环境中成功应用的关键。本篇详细介绍了数据库高可用方案、Sharding-JDBC 的故障切换机制、Sharding-Proxy 的集群部署,以及分布式治理功能。

资深架构师分享:深入剖析软件架构,探讨云计算、微服务、大数据等前沿技术。分享实践经验,促进技术交流,共同构建卓越系统。 1393

fork的底层实现

说起fork,我们就会联想它的一系列函数,vfork、clone、do_fork;这些函数都有一些什么区别呢?fork是全部复制,父进程的所有资源全部通过数据结构的复制“遗传”给子进程; clone是一个可选择的复制,通过参数的不同,来选择性地拷贝父进程的资源,没有拷贝的则通过指针的赋值,共享父进程的资源; vfork是一个没有参数的系统调用,除了拷贝父进程的内核栈空间和task_struct结

Zong__Zong的博客 877

PADS安装教程(超详细)

声明:个人实践 一、工具准备 pads9.5完整破解版百度网盘提取码【wjx9】 链接:https://pan.baidu.com/s/1pIP6BJO435ssmF7Hjwyz8A 提取码:wjx9 安装环境:win10 64位 二、开始解压安装 关闭杀毒,exe以管理员身份运行 点击【skip】,不然又得licese 点击【agree】 点击【modify】 设置安装的工具、路径及工程路径 设置完成后,开始【install】 在之后注册。 将Crack复制到PADS安装目录

qq_42057393的博客 5万+

Java基础——一文读懂Fork/Join框架

如图一个规模为T的任务划分成12个子任务,分别有4个线程在执行。如果当前线程没有可执行任务时,会从其他线程的任务队列中窃取任务来执行。工作窃取算法保证了cpu不会处于空闲状态。fork/Join框架的思想是将一个规模为n的大任务,fork成几个规模较小的K个子任务,最后合并所有子任务的结果,返回最终结果。由此我们可以看出,Java8的Stream并行流底层代码,确实采用了Fork/Join框架来实现。如下所示代码,利用Java8的并行流,对1到5的数进行相乘。接口TerminalOp。

mathGaosi的博客 626

UNext:基于 MLP 的快速医学图像分割网络

有代码,可深入学习轻量级分割模型的论文切入点 UNet 及其最新扩展(如 TransUNet)近年来一直是领先的医学图像分割方法。然而,这些网络无法有效地用于应用中的快速图像分割,因为它们参数繁重、计算复杂且使用缓慢。为此,我们提出了 UNeXt,它是一种基于卷积多层感知器(MLP)的图像分割网络。我们以有效的方式设计了 UNeXt,其中包括早期卷积阶段和潜在阶段的 MLP 阶段。我们提出了一个标记化的 MLP 块,我们可以在其中有效地标记和投影卷积特征,并使用 MLP 来对表示进行建模。

Philo的博客 3943

C++ 工程实践(9):数据抽象

陈硕 (giantchen_AT_gmail)http://blog.youkuaiyun.com/Solstice  http://weibo.com/giantchen陈硕关于 C++ 工程实践的系列文章: http://blog.youkuaiyun.com/Solstice/category/8

陈硕的Blog 1万+

java fork菜鸟_fork()函数的简单例子

1.fork()函数fork()是一个系统调用,用于创建进程。创建的这个进程与原来进程几乎完全相同。这个新产生的进程称为子进程。一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。需要注意的一点:就是调用fork之后,两个进程同时执行的代码段是fork函数之后的代码,...

weixin_30855927的博客 3648

QTableView实现表格加载百万条数据

本文介绍用QTableView实现加载100万条数据显示到表格。 1.创建工程 用Qt Creator创建Qt Widgets Application项目,基类选择QWidget,创建好了,如图: 2.添加QTableView控件 在widget.ui中添加QTableView控件,和QPushButton,采用栅格布局,如图: 3.添加函数 头文件 QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACE class Wid

丁爸的博客 8272

并发编程之:ForkJoin

大家好,我是小黑,一个在互联网苟且偷生的农民工。 在JDK1.7中引入了一种新的Fork/Join线程池,它可以将一个大的任务拆分成多个小的任务并行执行并汇总执行结果。 Fork/Join采用的是分而治之的基本思想,分而治之就是将一个复杂的任务,按照规定的阈值划分成多个简单的小任务,然后将这些小任务的结果再进行汇总返回,得到最终的任务。 分治法 分治法是计算机领域常用的算法中的其中一个,主要思想就是将将一个规模为N的问题,分解成K个规模较小的子问题,这些子问题相互独立且与原问题性质相同;求解出子

chinaherolts2008的博客 1328

Unity与IOS交互,调用IOS系统相机和相册

与IOS的交互,在步骤上要比android简单许多,不会产生因为系统版本,或者包名导致的许多问题。过程中最头疼的一个问题是IOS回调Unity,很简单的一个问题,搞了半天。

Hello Mingo 1万+

Qt 5.14安装(配置MSVC 2017)

本文主要介绍Qt MSVC的安装,VS2017.

ifeng12358的博客 3712

Fork/Join浅探与使用

声明: 本文部分文字介绍,直接摘录自《精通Java并发编程(第二版)》, 该书写得通俗易懂、且分析相对透彻,推荐阅读,具体信息见文末。 声明: 本文不会介绍具体的方法调用API,但是给出CountedCompleter<T>、RecursiveTask<V>、RecursiveAction的简单使用示例。 序言: JDK8开始,提供/优化了很多非常好用的并发组件,如parallelStream、CompletableFuture、ForkJoin等,本文初步学习ForkJoin。

JustryDeng 748

芒果YOLO11改进12:即插即用 | 独家原创改进最新PWConv核心结构|来自最新CVPR2023顶会,

即插即用 | 独家原创改进最新PWConv核心结构|来自最新CVPR2023顶会,

包括YOLOv5、YOLOv7、YOLOv8等模型改进 569

Conductor 微服务编排实战:基于 HTTP 任务的串行链、条件分支与 Fork/Join 并行编排

本篇文章以 Conductor 官方 Cookbook 中的微服务编排配方(microservice orchestration)为主线,讲解如何**不编写任何自定义 Worker**,仅靠内置的 HTTP 系统任务把散落在多个服务中的接口编排成可靠的工作流。你将掌握三种核心编排模式——HTTP 串行服务链、基于 SWITCH 的条件分支、基于 Fork/Join 的并行调用,并能在本地用 cur

gitblog_00624的博客 415

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

一个ForkJoin并行任务的实际应用

先交代背景,因为我有好多照片存在不同的电脑和移动硬盘备份,平时又喜欢摄影,有时候相机的照片和手机拍的需要同步到所有设备,保证所有设备上的照片都是一样的,但是有时候会各种原因导致图片不同步,人为查找排除很麻烦何况我有10000+照片(其实里面没有几张自己的。。),首先想到的是根据文件名判重,考虑到会有重名的文件,严谨起见采取对照片摘要MD5,再去判重

风起了云散了的专栏 5532

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

java stream 取某个字段_java8的函数式编程和stream使用心得

1:函数式编程在很多其他的编程语言里面,都可以实现函数式的编程,也就是函数可以作为变量去灵活使用,但是java一直都不可以,之前很多都使用一些匿名内部类这种丑的亚批的代码。java8之后算是可以使用伪函数式编程,其实也是应用了单方法接口去实现。并且设计出了lambda语法。1.1:lambda在lambda之前实现thread(真的很丑这代码)。 Thread thread = ne...

weixin_39844549的博客 3869

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

ForkJoin实现分而治之

把一个复杂的问题分解成多个相似的子问题,然后把子问题分解成更小的子问题,知道子问题简单到可以直接求解。 算法领域有分治算法(归并排序、快速排序都属于分治算法,二 分法查找也是一种分治算法);大数MapReduce也是。 [](()分治模型 分治任务可以分成两个阶段:任务分解,结果合并。 [](()Fork/Join的使用 Fork/Join计算框架主要包含两部分,一部分是分治任务的线程池ForkJoinPool,另一部分是分治任务ForkJoinTask。这两部分的关系类似ThreadPoolExecut

m0_69379016的博客 253

第四章JAVA并发

4.1 并发基础 4.2 所有锁原理 4.3 votaile原理 4.4 并发容器原理 4.5 Fork_Join原理 4.1 并发基础 CPU原理(哈哈,以后我当面试官了就问CPU原理) 核心是晶体管(一种方式找到数字且能计算) 不导电的硅+加某些东东变成半导体 5V通电代表1,不通电代表0 进程和线程区别–略 线程中start和run区别 start会创建一个新的子线程启动,run方法只是thread下一个普遍方法调用 线程实现方式 1 extends Thread重写run方法 2 implemen

weixin_40503364的博客 404

JAVA线程知识小集

1. interrupted与isInterrupted的区别 interrupted():测试当前线程是否已经是中断状态,执行后具有状态标志清除为false的功能。  isInterrupted():测试线程Thread对象是否已经是中断状态,但不清除状态标志。  方法: public static boolean interrupted(){     return currentThre...

m0_37822534的博客 232

Java高并发程序设计

第一章  走入并行世界   关于并行的两个定律: Amdahl定律 和Gustafson定律 考虑方向不同   Java内存模型 JMM 原子性 可见性 有序性   第二章 Java并行程序基础          线程创建: new Thread(Runable).start()     线程终止: stop 方法  会立即释放锁,导致数据不一致问题,已经废弃     线程中断...

筑梦者 720

JUC学习笔记

JUC是什么 JUC是JAVA中java.util.concurrent包的简称. 这个包里面的东西就是Doug Lea写的,它主要包括atomic支持原子操作类相关代码,locksjava中锁相关代码,还有其他并发容器相关代码. 在jdk官方手册中可以看到juc相关的jar包有三个。用中文概括一下,JUC的意思就是java并发编程工具包。 上下文切换的概念 CPU通过时间片分配算法来循环执行任务,当前执行一个时间片后会切换到下一个任务。 但是,在切换前会保存上一个任务的状态,以便下次切换会这个任务时,可以

Wynb1020的博客 728

java多线程编程基础

线程概念 创建新线程 从Thread派生; 实现Runnable接口(不需要返回结果); 通过 Callable 和 Future 创建线程(需要返回结果); 必须调用start()方法才能启动新线程 Thread.sleep()可以把当前线程暂停一段时间 线程的状态 一个线程对象只能调用一次start() Java线程对象Thread的状态包括: New / Runnable / Block...

wly5503的博客 384

Java并发编程实战六(2023-03-28 22:30)

这是前言Fork/Join框架是Java 7提供的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务(compute方法),最终汇总每个小任务结果后得到大任务结果的框架。我们再通过Fork和Join这两个单词来理解一下Fork/Join框架。Fork就是把一个大任务切分为若干子任务并行的执行,Join就是合并这些子任务的执行结果,最后得到这个大任务的结果。比如计算1+2+…+10000,可以分割成10个子任务,每个子任务分别对1000个数进行求和,最终汇总这10个子任务的结果。

qq_40662424的博客 257

学好并发编程必须要理解的三个核心问题

一些读者朋友留言说,并发编程很难,学习了很多的知识,但是在实际工作中却无从下手。对于一个线上产生的并发问题,又不知产生这个问题的原因究竟是什么。对于并发编程,感觉上似乎是掌握了,但是真正用起来却不是那么回事! 其实,造成这种现象的本质原因就是没有透彻的理解并发编程的精髓,而学好并发编程的关键是需要弄懂三个核心问题:分工、同步和互斥 需要更多Java知识点和面试题的朋友可以点一点下方链接免费领取 链接:1103806531暗号:优快云 分工 比较官方的解释为:分工就是将一个比较大的任务,拆分成多个大

XingXing_Java的博客 4372

Java杂录

在判断是否为空时可以用一些工具类以保证结果的准确性 数据库表除主键列外当需要保证单列值或多列组合值插入的数据是唯一参数时最好给其加上唯一索引,以保证数据的唯一性

豪华的博客 210

并发基础

前言 Concurrency Foundation 1. Synchronized 2. Atomic Access 3. Guarded blocks 4. Immutable Objects High Level Concurrency Objects 1. Lock Objects 2. Executors 2.1 Executor Interfaces execute call ...

Shelby Lee的博客 320
上一篇: java中用对象的引用去调用类的静态方法,会对引用做是否为空的校验么?
下一篇: 关于Java中ForkJoinPool.commonPool()详解
Jack_abu
博客等级 码龄10年 633粉丝 78原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jack_abu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值