【Java】ForkJoin 框架

news2025/6/2 15:50:17

在Java中,ForkJoin框架是并行编程的一个重要工具,它主要用于处理可以分解为多个子任务的复杂任务。ForkJoin框架的核心是ForkJoinPool,它是一个线程池,专门用于执行ForkJoinTask任务。通过将大任务分解为多个小任务,并在多个线程中并行执行这些小任务,ForkJoin框架可以显著提高程序的执行效率。

1.核心组件

ForkJoinPool

• 这是ForkJoin框架的核心线程池,用于管理和调度ForkJoinTask任务。

• 它使用工作窃取算法(work-stealing algorithm),允许空闲的线程从其他线程的任务队列中窃取任务来执行,从而提高线程的利用率。

• 示例代码:

    ForkJoinPool pool = new ForkJoinPool();

ForkJoinTask

• 这是ForkJoin框架中任务的抽象基类,所有自定义的任务都需要继承这个类。

• 通常使用RecursiveTask(有返回值的任务)或RecursiveAction(无返回值的任务)这两个子类来实现具体任务。

• 示例代码:

    public class MyTask extends RecursiveTask<Integer> {
        private int threshold;
        private int start;
        private int end;

        public MyTask(int threshold, int start, int end) {
            this.threshold = threshold;
            this.start = start;
            this.end = end;
        }

        @Override
        protected Integer compute() {
            int sum = 0;
            if (end - start <= threshold) {
                for (int i = start; i < end; i++) {
                    sum += i;
                }
            } else {
                int middle = (start + end) / 2;
                MyTask leftTask = new MyTask(threshold, start, middle);
                MyTask rightTask = new MyTask(threshold, middle, end);
                leftTask.fork(); // 异步执行子任务
                rightTask.fork(); // 异步执行子任务
                sum = leftTask.join() + rightTask.join(); // 等待子任务完成并获取结果
            }
            return sum;
        }
    }

2.工作窃取算法

• 工作窃取算法是一种高效的线程调度算法,用于解决线程空闲时的负载均衡问题。

• 每个线程都有自己的双端队列(deque),用于存储任务。

• 当一个线程的任务队列为空时,它可以从其他线程的任务队列中“窃取”任务来执行。

• 这种算法可以有效减少线程的空闲时间,提高线程的利用率。

3.使用示例

• 下面是一个完整的使用ForkJoin框架计算数组和的示例:

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

  public class ForkJoinExample {
      public static void main(String[] args) {
          int[] array = new int[1000000];
          for (int i = 0; i < array.length; i++) {
              array[i] = i;
          }

          ForkJoinPool pool = new ForkJoinPool();
          SumTask task = new SumTask(array, 0, array.length);
          int sum = pool.invoke(task);
          System.out.println("Sum: " + sum);
      }
  }

  class SumTask extends RecursiveTask<Integer> {
      private static final int THRESHOLD = 1000;
      private int[] array;
      private int start;
      private int end;

      public SumTask(int[] array, int start, int end) {
          this.array = array;
          this.start = start;
          this.end = end;
      }

      @Override
      protected Integer compute() {
          if (end - start <= THRESHOLD) {
              int sum = 0;
              for (int i = start; i < end; i++) {
                  sum += array[i];
              }
              return sum;
          } else {
              int middle = (start + end) / 2;
              SumTask leftTask = new SumTask(array, start, middle);
              SumTask rightTask = new SumTask(array, middle, end);
              leftTask.fork();
              rightTask.fork();
              return leftTask.join() + rightTask.join();
          }
      }
  }

4.优势

• 并行处理:通过将任务分解为多个子任务,并在多个线程中并行执行,可以显著提高程序的执行效率。

• 负载均衡:工作窃取算法可以有效解决线程空闲时的负载均衡问题,提高线程的利用率。

• 易于使用:ForkJoin框架提供了简单易用的API,使得并行任务的实现变得非常方便。

5.注意事项

• 任务分解粒度:任务分解的粒度需要适中。如果任务分解得太细,会导致线程的调度开销过大;如果任务分解得太粗,又无法充分利用多核CPU的优势。

• 线程池大小:合理配置ForkJoinPool的线程池大小,通常建议设置为CPU核心数的两倍左右。

• 线程安全:虽然ForkJoin框架本身是线程安全的,但在任务执行过程中,如果需要访问共享资源,仍然需要注意线程安全问题。

通过合理使用ForkJoin框架,可以有效提高Java程序的并行处理能力,从而提升程序的性能。

public class ForkJoinPoolTest extends RecursiveTask<Long> {

    private static final int THRESHOLD = 500;
    long[] array;
    int start;
    int end;

    ForkJoinPoolTest(long[] array, int start, int end) {
        this.array = array;
        this.start = start;
        this.end = end;
    }

    public static void main(String[] args) {
        long[] arrays = new long[1000];
        long expecteSum = 0;
        for (int i = 0; i < arrays.length; i++) {
            arrays[i] = i;
            expecteSum = expecteSum + arrays[i];
        }
        System.out.println(expecteSum);

        ForkJoinPoolTest forkJoinPoolTest = new ForkJoinPoolTest(arrays, 0, arrays.length);
        long startTime = System.currentTimeMillis();
        Long result = ForkJoinPool.commonPool().invoke(forkJoinPoolTest);
        long endTime = System.currentTimeMillis();


        System.out.println("fork/join sum:" + result + ",耗时:" + (endTime - startTime));
    }

    @Override
    protected Long compute() {
        //如果任务太小
        if (end - start <= THRESHOLD) {
            System.out.println("start=" + start + ",end=" + end);
            long sum = 0;
            for (int i = start; i < end; i++) {
                sum = sum + this.array[i];
                try {
                    TimeUnit.MILLISECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return sum;
        }
        int middle = (end + start) / 2;
        ForkJoinPoolTest joinPoolTest1 = new ForkJoinPoolTest(this.array, start, middle);
        ForkJoinPoolTest joinPoolTest2 = new ForkJoinPoolTest(this.array, middle, end);
        invokeAll(joinPoolTest1, joinPoolTest2);
        Long result1 = joinPoolTest1.join();
        Long result2 = joinPoolTest2.join();
        long result = result1 + result2;
        System.out.println("result = " + (result1 + result2));
        return result;
    }

}

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

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

相关文章

桥 接 模 式

在玩游戏的时候我们常常会遇到这样的机制&#xff1a;我们可以随意选择不同的角色&#xff0c;搭配不同的武器。这时只有一个抽象上下文的策略模式就不那么适用了&#xff0c;因为一旦我们使用继承的方式&#xff0c;武器和角色总有一方会变得难以扩展。这时&#xff0c;我们就…

基于 Flink+Paimon+Hologres 搭建淘天集团湖仓一体数据链路

摘要&#xff1a;本文整理自淘天集团高级数据开发工程师朱奥老师在 Flink Forward Asia 2024 流式湖仓论坛的分享。内容主要为以下五部分&#xff1a; 1、项目背景 2、核心策略 3、解决方案 4、项目价值 5、未来计划 01、项目背景 1.1 当前实时数仓架构 当前的淘天实时架构是从…

多杆合一驱动城市空间治理智慧化

引言&#xff1a;城市“杆林困境”与智慧化破局 走在现代城市的街道上&#xff0c;路灯、监控、交通信号灯、5G基站等杆体林立&#xff0c;不仅侵占公共空间&#xff0c;更暴露了城市治理的碎片化问题。如何让这些“沉默的钢铁”升级为城市的“智慧神经元”&#xff1f;答案在…

用QT写一个车速表

主要包含以下绘制步骤&#xff1a; 1、绘制画布&#xff1a; /** 绘制画布 */ void Widget::initCanvas(QPainter &painter) {//消除锯齿painter.setRenderHint(QPainter::Antialiasing,true);//设置底色painter.setBrush(QColor(0,0,0));painter.drawRect(rect());//平移…

数控技术应用理实一体化平台VR实训系统

::产品概述:: 目前我国本科类院校学生普遍存在的问题就是缺少对实际工作的了解&#xff0c;一直在学习相关专业的理论知识&#xff0c;对社会的相关企业的用人情况不了解。这也就直接导致了毕业的学生和社会上的用人单位需求有点脱节&#xff0c;这也是由于我国的现行本科教育侧…

C# 将HTML文档、HTML字符串转换为图片

在.NET开发中&#xff0c;将HTML内容转换为图片的需求广泛存在于报告生成、邮件内容存档、网页快照等场景。Free Spire.Doc for .NET作为一款免费的专业文档处理库&#xff0c;无需Microsoft Word依赖&#xff0c;即可轻松实现这一功能。本文将深入解析HTML文档和字符串转图片两…

界面控件DevExpress WinForms v24.2新版亮点:富文本编辑器功能全新升级

DevExpress WinForms拥有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForms能完美构建流畅、美观且易于使用的应用程序&#xff0c;无论是Office风格的界面&#xff0c;还是分析处理大批量的业务数据&#xff0c;它都能轻松胜…

华为云Flexus+DeepSeek征文|华为云 Flexus X 加速 Dify 平台落地:高性能、低成本、强可靠性的云上选择

目录 前言 1 一键部署 Dify 平台的完整步骤 1.1 选择模板 1.2 参数配置 1.3 资源栈设置 1.4 配置确认与部署 2 Flexus X 服务器的技术优势 2.1 柔性算力随心配 2.2 一直加速一直快 2.3 越用越省降本多 2.4 安全可靠更放心 3 Flexus X 在 Dify 解决方案中的性能体验…

Jenkins 2.479.1安装和邮箱配置教程

1.安装 在JDK安装并设置环境变量完成后&#xff0c;下载官网对应的war版本&#xff0c;在对应目录下打开命令行窗口并输入 java -jar jenkins.war其余参数感兴趣可以自行查阅&#xff0c;这里启动的 jenkins 服务默认占用8080端口&#xff0c;在浏览器输入 localhost:8080进入…

DFS入门刷题c++

目录 821. 跳台阶 - AcWing题库 ​92. 递归实现指数型枚举 - AcWing题库 ​P1706 全排列问题 - 洛谷 (luogu.com.cn) P1157 组合的输出 - 洛谷 (luogu.com.cn) ​P1036 [NOIP 2002 普及组] 选数 - 洛谷 (luogu.com.cn) P2089 烤鸡 - 洛谷 (luogu.com.cn) P1088 [NOIP 2…

ToolsSet之:十六进制及二进制编辑运算工具

ToolsSet是微软商店中的一款包含数十种实用工具数百种细分功能的工具集合应用&#xff0c;应用基本功能介绍可以查看以下文章&#xff1a; Windows应用ToolsSet介绍https://blog.csdn.net/BinField/article/details/145898264 ToolsSet中Number菜单下的Hex Operate工具可以进…

【Python训练营打卡】day40 @浙大疏锦行

DAY 40 训练和测试的规范写法 知识点回顾&#xff1a; 1. 彩色和灰度图片测试和训练的规范写法&#xff1a;封装在函数中 2. 展平操作&#xff1a;除第一个维度batchsize外全部展平 3. dropout操作&#xff1a;训练阶段随机丢弃神经元&#xff0c;测试阶段eval模式关闭dropo…

MCP Server的五种主流架构:从原理到实践的深度解析

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 在AI大模型与外部数据交互的浪潮中&#xff0c;MCP Server&#xff08;Model Context Protocol Server&#xff09;已成为连接模型与现实世界的桥梁。本文…

跨协议协同智造新实践:DeviceNet-EtherCAT网关驱动汽车焊接装配效能跃迁

在汽车制造领域&#xff0c;机器人协作对于提升生产效率与产品质量至关重要。焊接、装配等关键环节&#xff0c;需要机器人与各类设备紧密配合。JH-DVN-ECT疆鸿智能的devicenet从站转ethercat主站协议网关&#xff0c;成为实现这一高效协作的得力助手&#xff0c;尤其是在连接欧…

让 Deepseek 写一个尺码计算器

下面是一个简单的尺码计算器微信小程序的代码实现&#xff0c;包含页面布局、逻辑处理和样式。 1. 项目结构 size-calculator/ ├── pages/ │ ├── index/ │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── inde…

代码随想录算法训练营第60期第五十三天打卡

大家好&#xff0c;我们今天来到了最后一章图论&#xff0c;其实图论比较难&#xff0c;涉及的算法也比较多&#xff0c;今天比较重要的就是深度优先搜索与广度优先搜索&#xff0c;后面的迪杰斯特拉算法等算法在我们求最短路都会涉及到&#xff0c;还有最近公共祖先&#xff0…

Nacos实战——动态 IP 黑名单过滤

1、需求分析 一些恶意用户&#xff08;‏可能是黑客、爬虫、DDoS ؜攻击者&#xff09;可能频繁请求服务器资​源&#xff0c;导致资源占用过高。针对这种问题&#xff0c;可以通过IP‏ 封禁&#xff0c;可以有效拉؜黑攻击者&#xff0c;防止资源​被滥用&#xff0c;保障合法…

实验设计与分析(第6版,Montgomery)第5章析因设计引导5.7节思考题5.14 R语言解题

本文是实验设计与分析&#xff08;第6版&#xff0c;Montgomery著&#xff0c;傅珏生译) 第5章析因设计引导5.7节思考题5.14 R语言解题。主要涉及方差分析&#xff0c;正态假设检验&#xff0c;残差分析&#xff0c;交互作用图。 dataframe<-data.frame( strengthc(9.60,9.…

在Ubuntu20.04上安装ROS Noetic

本章教程,主要记录在Ubuntu20.04上安装ROS Noetic。 一、添加软件源 sudo sh -c . /etc/lsb-release && echo "deb http://mirrors.tuna.tsinghua.edu.cn/ros/ubuntu/ `lsb_release -cs` main" > /etc/apt/sources.list.d/ros-latest.list二、设置秘钥 …

python里面导入yfinance的时候报错

我的代码&#xff1a; import yfinance as yf import os proxy http://127.0.0.1:7890 # 代理设置&#xff0c;此处修改 os.environ[HTTP_PROXY] proxy os.environ[HTTPS_PROXY] proxydata yf.download("AAPL",start"2010-1-1",end"2021-8-1&quo…