ForkJoinPool的使用及基本原理

news2024/11/23 20:04:22

文章目录

  • 1. 简介
  • 2. ForkJoinPool的基本原理
    • 2.1 工作窃取算法(Work Stealing)
      • 2.1.1 工作窃取算法的定义和特点
      • 2.1.2 工作队列和双端队列的作用与区别
    • 2.2 分治策略(Divide and Conquer)
      • 2.2.1 分治策略的概念和应用场景
      • 2.2.2 任务拆分与合并的原则
  • 3. ForkJoinPool的使用步骤
    • 3.1 创建ForkJoinPool实例
    • 3.2 定义ForkJoinTask子类
      • 3.2.1 RecursiveTask的使用
      • 3.2.2 RecursiveAction的使用
    • 3.3 提交任务到ForkJoinPool
  • 4. 总结

1. 简介

ForkJoinPool是Java中的并行执行框架,用于实现任务的拆分和合并。它基于工作窃取算法(Work Stealing)和分治策略(Divide and Conquer),可以有效地利用多核处理器的性能,提升任务的执行效率。

  • 分布式计算与并行计算的关系
    并行计算是指将一个大任务拆分成多个子任务,并且这些子任务可以同时执行,从而加快整体任务的完成速度。分布式计算是指将任务分配到多个计算节点上进行并行计算,节点之间通过网络进行通信和协调。ForkJoinPool是在单台计算机上进行并行计算的工具,它可以利用多个线程,并行地执行任务。

2. ForkJoinPool的基本原理

2.1 工作窃取算法(Work Stealing)

2.1.1 工作窃取算法的定义和特点

工作窃取算法是一种用于任务调度的并行计算策略,它的主要特点如下:

  • 每个工作线程都维护一个工作队列,用于存放待执行的任务。
  • 当一个工作线程完成自己的任务后,它可以从其他工作线程的工作队列中窃取任务执行。
  • 工作线程可以从双端队列的两端进行操作,被偷取的任务在双端队列的末尾添加。

工作窃取算法的主要目标是实现任务的负载均衡。由于每个线程都有自己的工作队列,当某个线程的队列空闲时,它可以从其他线程的队列中偷取任务来执行,从而避免了线程的空闲等待。这样可以充分利用处理器的多核特性,提高整个任务的执行效率。

2.1.2 工作队列和双端队列的作用与区别

  • 工作队列:每个工作线程都有自己的工作队列,用于存放自己的任务。当线程执行任务时,它从自己的工作队列中获取任务进行执行。
  • 双端队列:所有工作线程共享的双端队列,用于存放被偷取的任务。当一个线程完成自己的任务后,它可以从双端队列的末尾窃取任务来执行。

工作队列和双端队列的作用是不同的。工作队列主要用于存放自己的任务,保证每个线程都有任务可执行。而双端队列主要用于存放被偷取的任务,提供给其他线程进行任务窃取。工作队列是每个线程私有的,而双端队列是所有线程共享的。

2.2 分治策略(Divide and Conquer)

2.2.1 分治策略的概念和应用场景

分治策略是将一个大任务拆分成多个小任务,并且这些小任务可以独立地执行,最后将它们的结果合并得到整个任务的结果。分治策略的基本步骤包括:

  • 分解:将大任务拆分成多个小任务。
  • 解决:独立地执行这些小任务。
  • 合并:将小任务的结果合并得到整个任务的结果。

分治策略通常应用于可以被递归地划分成更小规模的问题。通过将任务拆分成多个子任务,并行地执行这些子任务,可以提高任务的执行效率和并行度。分治策略在并行计算中被广泛应用,例如在排序算法(如归并排序和快速排序)以及图算法(如图搜索和最短路径算法)等领域。
在这里插入图片描述

2.2.2 任务拆分与合并的原则

在应用分治策略时,任务的拆分和合并需要遵循一些原则:

  • 拆分原则:大任务应该被拆分成多个相互独立的小任务。每个小任务应该尽可能平均地分配给工作线程,以保证负载均衡。
  • 合并原则:小任务的结果应该能够被合并成整个任务的结果。合并的操作应该是可逆的,即可以从小任务的结果恢复出整个任务的结果。

拆分和合并的原则可以根据具体的任务进行调整,以适应不同的应用场景和需求。通过合理地设计任务的拆分和合并策略,可以充分利用分治策略的优势,提高并行计算的性能和效率。

3. ForkJoinPool的使用步骤

3.1 创建ForkJoinPool实例

ForkJoinPool forkJoinPool = new ForkJoinPool();

3.2 定义ForkJoinTask子类

3.2.1 RecursiveTask的使用

RecursiveTask也是一个抽象类,用于表示带有返回值的任务。它同样继承自ForkJoinTask类,可以通过继承RecursiveTask类并实现compute()方法来创建自定义的分治任务。

import java.util.concurrent.RecursiveTask;

public class Task extends RecursiveTask<Integer> {
    /**
     * 起始值
     */
    private int start;
    /**
     * 结束值
     */
    private int end;
    /**
     * 临界值
     */
    private int temp = 10;

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

    @Override
    protected Integer compute() {
        // 当开头与结尾之差小于临界值时
        if ((end - start) < temp) {
            // 记录计算结果
            int sum = 0;
            // 累加开头-结尾的值
            for (int i = start; i <= end; i++) {
                sum += i;
            }
            // 返回结果
            return sum;
        } else {
            // 取中间值
            int middle = (start + end) / 2;
            // 计算开头-中间
            Task task1 = new Task(start, middle);
            // 向线程池中添加此任务
            task1.fork();
            // 计算中间-结尾
            Task task2 = new Task(middle + 1, end);
            // 向线程池中添加此任务
            task2.fork();
            // 合并结果
            return task1.join() + task2.join();
        }
    }
}

3.2.2 RecursiveAction的使用

RecursiveAction是一个抽象类,用于表示没有返回值的任务。它继承自ForkJoinTask类,可以通过继承RecursiveAction类并实现compute()方法来创建自定义的分治任务。

public class RaskDemo extends RecursiveAction {
    /**
     *  每个"小任务"最多只打印20个数
      */
    private static final int MAX = 20;

    private int start;
    private int end;

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

    @Override
    protected void compute() {
        //当end-start的值小于MAX时,开始打印
        if((end-start) < MAX) {
            for(int i= start; i<end;i++) {
                System.out.println(Thread.currentThread().getName()+"i的值"+i);
            }
        }else {
            // 将大任务分解成两个小任务
            int middle = (start + end) / 2;
            RaskDemo left = new RaskDemo(start, middle);
            RaskDemo right = new RaskDemo(middle, end);
            left.fork();
            right.fork();
        }
    }
}

3.3 提交任务到ForkJoinPool

public class Main {

    public static void main(String[] args) {
        // 创建任务
        Task task = new Task(1, 100);
        // 创建 ForkJoin 线程池
        ForkJoinPool threadPool = new ForkJoinPool();
        // 提交任务
        ForkJoinTask<Integer> future = threadPool.submit(task);
        try {
            // 获取结果
            Integer result = future.get();
            // 输出结果
            System.out.println(result);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        } finally {
            // 关闭线程池
            threadPool.shutdown();
        }
    }
}

4. 总结

以上是关于ForkJoinPool的使用及基本原理的详细内容。通过创建ForkJoinPool实例、定义ForkJoinTask子类、提交任务到ForkJoinPool以及获取任务结果,可以灵活地应用ForkJoinPool实现并行计算。在使用过程中,合理设置并行度、选择适当的任务拆分粒度、避免任务依赖与阻塞以及正确处理错误和异常等方面的调优和最佳实践能够提升性能和效果。

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

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

相关文章

Linux中的软件管家——yum

目录 ​编辑 一&#xff0c;软件安装的方式 二&#xff0c;对yum的介绍 1.yum的作用 2&#xff0c;yum的库 三&#xff0c;yum下载软件的操作 1.yumlist 2.yuminstall 3.yumremove 四&#xff0c;yum源的转换 一&#xff0c;软件安装的方式 软件安装的方式大概分为三种…

AI消除笔快速去除脸部痘痘疤痕,新手变高手!

美颜的途径有很多&#xff0c;比较实用的是祛痘和柔肤。祛除人物脸部的痘痕有多种方法&#xff0c;比较常见且普遍的就是使用PS“污点去除”工具来去除痘痕&#xff0c;以及柔化皮肤。 除了PS我们还可以使用AI图片消除工具&#xff0c;这就对手残党非常的友好了。 牛学长图片…

IDEA快捷键第二版

1、选择当前行和上一行 按住 Shift键 再按两下向上键&#xff08; ↑ &#xff09;&#xff0c;按两下选两行&#xff0c;以此类推 2、将整个方法上移动 文本光标应放在方法的标头处&#xff0c;按住Ctrl Shift 向上键&#xff08; ↑ &#xff09;&#xff0c; 3、解包 …

JavaScript-----轮播图案例展示

前言&#xff1a; 这一期我们去通过JavaScript的代码实现轮播图的制作&#xff0c;下面有效果展示和代码资源&#xff0c;其中的图片资源和代码资源我都上传上去了&#xff0c;如果需要运行的话&#xff0c;你们可以去直接下载下来。希望各位喜欢&#xff01; 效果展示 16941…

外汇交易技巧分享:利用MT4交易平台进行精准的外汇技术分析

在外汇交易市场中&#xff0c;技术分析是一种重要的决策工具&#xff0c;能够帮助交易者预测价格走势和制定交易策略。而MT4交易平台作为一种功能强大、广泛应用的交易软件&#xff0c;为交易者提供了丰富的技术分析工具和功能。本文将与大家分享几个利用MT4交易平台(可在mtw.s…

C++设计模式_03_模板方法Template Method

文章目录 1. 设计模式分类1.1 GOF-23 模式分类1.2 从封装变化角度对模式分类 2. 重构&#xff08;使用模式的方法&#xff09;2.1 重构获得模式 Refactoring to Patterns2.2 重构关键技法 3. “组件协作”模式4. Template Method 模式4.1 动机&#xff08; Motivation&#xff…

北京融资融券两融账户最低利率怎么申请?哪家券商无门槛!

北京融资融券利率申请可以低至5%或者以下&#xff0c;无门槛5%支持线上办理&#xff0c;股票成本价&#xff0c;只有极少数的券商可以实现。 北京办理融资融券两融业务如果没有找对正确的开户渠道&#xff0c;自己办理是按照券商默认的利率收取&#xff0c;默认利率8.35%&#…

C#文件重命名工具

文章目录 工具背景4个文件介绍RenamesSpecificPrefixFile.exe.configDataSave.txt 工具介绍重命名的存储方式 文件夹介绍源文件夹 结果使用【PDF】/【视频】重名时坚持拷贝 可能的报错 工具背景 你上次选的这三个选项&#xff0c;他会记住&#xff0c;后面再打开就是上次的位置…

使用本地mysql+linux实现mysql主从同步

1.配置linux 保证linux已经安装好了mysql1.1修改该linux配置文件 vim /etc/my.cnf1.2重启linux的mysql systemctl restart mysqld1.3使用账户密码登录linux中的mysql,查看是否配置成功 mysql> show master status;若显示有FIile和Posttion就表示注linux的主节点配置成功…

基于uwb和IMU融合的三维空间定位算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ..........................................................................kkk 0; for E…

【算法题】小红书2023秋招提前批算法真题解析

文章目录 题目来源T1&#xff1a;5900: 【DP】小红书2023秋招提前批-连续子数组最大和5801: 【二分查找】小红书2023秋招提前批-精华帖子解法1——排序滑动窗口解法2——前缀和 二分查找 5000: 【模拟】小红书2023秋招提前批-小红的数组构造解法——数学 5300: 【哈希表】小红…

欧洲电子产品CE认证 CE-EMC认证办理

任何的产品想要在欧洲自由贸易必须通过CE认证&#xff0c;在产品上加贴CE标志。CE标志表示产品已经达到了欧盟指令规定的安全要求;是企业对消费者的一种承诺&#xff0c;增加了消费者对产品的信任程度。 贴有CE标志的产品将降低在欧洲市场上销售的风险。这些风险包括&#xff1…

C++11新特性③ | 可变参数模板介绍

目录 1、引言 2、可变参数模板函数 2.1、可变参数模板函数的定义 2.2、参数包的展开 3、可变参数模板类 3.1、继承方式展开参数包 3.2、模板递归和特化方式展开参数包 VC常用功能开发汇总&#xff08;专栏文章列表&#xff0c;欢迎订阅&#xff0c;持续更新...&#xff…

RabbitMQ: return机制

1. Return机制 Confirm只能保证消息到达exchange&#xff0c;无法保证消息可以被exchange分发到指定queue。 而且exchange是不能持久化消息的&#xff0c;queue是可以持久化消息。 采用Return机制来监听消息是否从exchange送到了指定的queue中 2.Java的实现方式 1.导入依赖 &l…

基于googlenet网络的动物种类识别算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ................................................................. % 获取输入层的尺寸 Inp…

异步编程 - 13 高性能线程间消息传递库 Disruptor

文章目录 Disruptor概述Disruptor中的核心术语Disruptor 流程图 Disruptor的特性详解基于Disruptor实现异步编程 Disruptor概述 Disruptor是一个高性能的线程间消息传递库&#xff0c;它源于LMAX对并发性、性能和非阻塞算法的研究&#xff0c;如今构成了其Exchange基础架构的核…

NIFI使用InvokeHTTP发送http请求

说明 这里介绍四种平时常用的http请求方法&#xff1a;GET、POST、PUT、DELETE。 在官方的介绍文档中关于InvokeHTTP处理器的描述是这么说的&#xff1a; An HTTP client processor which can interact with a configurable HTTP Endpoint. The destination URL and HTTP Met…

java 企业工程管理系统软件源码 自主研发 工程行业适用

工程项目管理软件&#xff08;工程项目管理系统&#xff09;对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营&#xff0c;全过程、全方位的对项目进行综合管理 工程项目各模块及其功能点清单 一、系统管理 1、数据字典&am…

网工内推 | 云架构运维、网络工程师,base北京,最高20k

01 协合新能源 招聘岗位&#xff1a;IT运维工程师 职责描述&#xff1a; 1、对集团内使用云计算架构&#xff08;Kubernetes&#xff09;的系统进行规划、运维及管理相关工作。 2、对集团数据中心系统的大数据基础架构&#xff08;Cloudera Distribution Hadoop&#xff09;的…

【办公类-16-06】20230901大班运动场地分配表-斜线排列、5天循环、不跳节日,手动修改节日”(python 排班表系列)

背景需求&#xff1a; 大班组长发来一个“运动排班”的需求表&#xff1a;“就是和去年一样的每个班的运动排班&#xff0c;就因为今年大班变成7个班&#xff0c;要重新做一份&#xff0c;不然我就用去年的那份了&#xff08;8个大班排班&#xff09;” &#xff08;拆了中8班…