ForkJoinPool的使用以及基本原理

news2024/9/20 14:44:43

文章目录

  • 一、ForkJoinPool简介
  • 二、ForkJoinPool的基本原理
    • 1. 分治法
    • 2. 工作窃取
  • 三、ForkJoinPool的使用场景
    • 1. 递归式的任务分解:
    • 2. 数据并行处理:
    • 3. 合并结果:
    • 4. 并行递归算法:
    • 5. 小结:
  • 四、ForkJoinPool的基本使用
    • 1. 计算1到1亿累加和:
    • 2. 运行结果:
    • 3. 案例分析:

一、ForkJoinPool简介

fork/join

  1. Fork/Join框架是Java7提供的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。
  2. 使用Fork/Join框架可以简化并发任务的编写和调度,提高并行任务的执行效率。它适用于那些可以被划分成多个独立子任务并且子任务之间没有依赖关系的情况。通过将大任务分割成小任务并使用Fork/Join框架执行,可以充分利用多核处理器的性能,提高程序的并发能力。

二、ForkJoinPool的基本原理

  1. ForkJoinPool是Java并发编程中的一个线程池实现,它特别适用于任务分解与合并的场景。
  2. ForkJoinPool的基本原理是基于“工作窃取”(work-stealing)算法。它维护着一个工作队列(WorkQueue)的数组,每个工作队列对应一个工作线程(WorkerThread)。当一个线程需要执行一个任务时,它会将任务添加到自己的工作队列中。当一个线程的工作队列为空时,它会从其他线程的工作队列中“窃取”一个任务来执行。这个“窃取”操作可以在不同的线程间实现任务的负载均衡。
  3. ForkJoinPool的任务是通过ForkJoinTask来表示的,ForkJoinTask是一个抽象类,它提供了两个子类:RecursiveAction和RecursiveTask。
    123
    RecursiveAction表示没有返回值的任务,而RecursiveTask表示有返回值的任务。
  4. 当一个任务被提交到ForkJoinPool时,它会被划分成更小的子任务,然后分配给不同的工作线程执行。如果一个任务的划分后的子任务数超过了一个阈值(通常是系统的处理器数量),那么这个任务就会被分割成更小的子任务,并通过递归的方式继续划分和执行。当一个工作线程执行完自己的任务后,它会从自己的工作队列中获取一个待执行的任务,或者从其他工作线程的工作队列中“窃取”一个任务来执行。这样,ForkJoinPool就实现了任务的自动划分、负载均衡和并行执行。
  5. 总结起来,ForkJoinPool的原理可以概括为以下几个步骤:
  • 将任务划分成更小的子任务;
  • 将子任务分配给不同的工作线程执行;
  • 工作线程执行自己的任务,并从工作队列中获取待执行的任务;
  • 如果工作队列为空,工作线程可以从其他工作线程的工作队列中“窃取”一个任务来执行;
  • 重复执行步骤3和步骤4,直到所有的任务都执行完毕。

1. 分治法

  1. ForkJoinPool是Fork/Join框架中的核心组件,它使用分治法来实现任务的并行执行。分治法是一种将大问题划分成小问题,并通过递归地解决小问题来解决大问题的方法。

  2. 在Fork/Join框架中,使用ForkJoinPool来管理工作线程和任务的执行。当一个任务被提交给ForkJoinPool时,ForkJoinPool会将任务划分成更小的子任务,每个子任务都是一个ForkJoinTask。如果一个任务的划分后的子任务数超过了一个阈值(通常是系统的处理器数量),那么这个任务就会被继续划分成更小的子任务,直到满足划分条件。
    forkjoin

  3. ForkJoinPool的分治法可以通过以下步骤来实现:

  • 判断任务是否足够小,如果足够小,则直接执行任务并返回结果。
  • 如果任务太大,将任务划分成更小的子任务。
  • 将子任务提交给ForkJoinPool进行执行。
  • 等待子任务执行完成,并获取子任务的结果。
  • 合并子任务的结果,得到最终的结果。
  1. 通过不断地划分和执行子任务,最终可以将大任务分解成多个小任务,并行地执行这些小任务,最后再将小任务的结果合并得到最终结果。这种分治的思想能够提高任务的并行性和执行效率。

  2. 总结起来,ForkJoinPool使用分治法来实现任务的并行执行。它通过将大任务划分成小任务,并使用递归的方式执行和合并这些小任务,能够充分利用多核处理器的性能,提高程序的并发能力。

2. 工作窃取

ForkJoinPool是Java并发包中用于支持任务并行执行的线程池,它采用了工作窃取机制来提高任务的执行效率。

工作窃取机制是指当某个线程完成了自己的任务后,它可以从其他线程的任务队列中窃取任务来执行。这种机制可以使得线程的负载均衡,提高整体的并发性能。

在ForkJoinPool中,每个线程都有一个自己的任务队列,用于存放待执行的任务。当一个线程没有任务可执行时,它可以从其他线程的任务队列中窃取任务来执行。
工作窃取

具体的工作窃取过程如下:

1、当一个线程完成了自己的任务后,它会尝试从其他线程的任务队列中窃取任务。为了避免线程之间争夺任务队列的同步问题,ForkJoinPool采用了双端队列,即每个线程都有一个自己的任务队列和一个用于窃取任务的双端队列。

2、窃取任务时,线程会从其他线程的双端队列的尾部窃取任务。这是因为尾部的任务是最新加入的任务,可能是最热门的任务,窃取这些任务可以提高执行效率。

3、当一个线程窃取到了任务后,它会将任务添加到自己的任务队列中,并开始执行该任务。

通过工作窃取机制,ForkJoinPool可以实现任务的自动负载均衡。当某个线程的任务队列较长时,其他线程可以窃取其中的任务来执行,从而使得线程的负载更均衡,提高整体的并发性能。

需要注意的是,工作窃取机制适用于任务之间的计算密集型操作,如果任务之间存在IO等阻塞操作,可能会导致线程的工作窃取效果不明显。此外,工作窃取机制也可能会引发一些问题,如线程间的竞争和任务的执行顺序问题,需要注意处理。

三、ForkJoinPool的使用场景

1. 递归式的任务分解:

当需要处理一个大型任务,并且这个任务可以被递归地分解成更小的子任务时,ForkJoinPool是一个很好的选择。它能够高效地将任务分解成更小的部分,并且可以并行地执行这些子任务。

2. 数据并行处理:

如果需要对一个数据集合进行并行处理,ForkJoinPool可以将数据分割成更小的部分,并且允许多个线程并行地处理这些部分。这对于一些需要对大量数据进行计算或处理的场景非常有用。

3. 合并结果:

当任务的执行结果需要合并到一个最终结果时,ForkJoinPool可以方便地实现这个功能。它能够将子任务的结果合并到父任务中,从而得到最终的结果。

4. 并行递归算法:

某些算法的实现需要使用递归方式进行计算,并且可以通过并行化来提高性能。ForkJoinPool提供了适合这种场景的框架和工具,可以简化并行递归算法的实现。

5. 小结:

需要注意的是,ForkJoinPool适用于处理计算密集型的任务,而不是I/O密集型的任务。因为ForkJoinPool的工作窃取算法需要多个线程共享一个任务队列,如果任务涉及到大量的I/O操作,可能会导致线程长时间等待,从而降低性能。对于I/O密集型的任务,建议使用其他适合的并发框架或技术。

四、ForkJoinPool的基本使用

1. 计算1到1亿累加和:

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

public class SumCalculator extends RecursiveTask<Long> {
    private static final long THRESHOLD = 10000; // 阈值,当任务大小小于等于阈值时,直接计算结果
    private long start;
    private long end;

    public SumCalculator(long start, long end) {
        this.start = start;
        this.end = end;
    }

    @Override
    protected Long compute() {
        if (end - start <= THRESHOLD) {
            long sum = 0;
            for (long i = start; i <= end; i++) {
                sum += i;
            }
            return sum;
        } else {
            long mid = (start + end) / 2;
            SumCalculator leftTask = new SumCalculator(start, mid);
            SumCalculator rightTask = new SumCalculator(mid + 1, end);

            leftTask.fork(); // 分解左边任务,异步执行
            rightTask.fork(); // 分解右边任务,异步执行

            long leftSum = leftTask.join(); // 等待左边任务执行完成并获取结果
            long rightSum = rightTask.join(); // 等待右边任务执行完成并获取结果

            return leftSum + rightSum; // 合并子任务的结果
        }
    }

    public static void main(String[] args) {
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        SumCalculator calculator = new SumCalculator(1, 100000000);
        long sum = forkJoinPool.invoke(calculator); // 启动任务并获取结果
        System.out.println("Sum: " + sum);
    }
}

2. 运行结果:

计算结果

3. 案例分析:

  1. 在上面的代码中,我们定义了一个继承自RecursiveTask的SumCalculator类,用于计算给定范围内的数子累加和。在compute()方法中,我们通过判断任务的大小是否小于等于阈值来决定是直接计算结果还是继续分解任务。如果任务大小小于等于阈值,直接计算结果;否则,将任务分解成两个子任务并异步执行,并通过join()方法等待子任务执行完成并获取结果,最后将子任务的结果合并返回。

  2. 在main()方法中,我们创建了一个ForkJoinPool实例,并通过invoke()方法启动任务并获取结果,最后打印出累加和的结果。

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

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

相关文章

第13节:特色数据——把握宏观经济脉搏

文章目录 中国主要宏观经济指标相关接口本节课任务 中国主要宏观经济指标 GDP&#xff08;国内生产总值&#xff09;&#xff1a;GDP是衡量一个国家或地区经济活动总量的指标&#xff0c;代表了一定时期内该国或地区所有最终产品和服务的市场价值总和。它反映了一个经济体的整体…

【花雕】青少年机器人教育等级评测模拟题_20200715(一级)

随着科技的不断进步&#xff0c;机器人技术已经成为了一个重要的领域。在这个领域中&#xff0c;机械结构是机器人设计中至关重要的一部分&#xff0c;它决定了机器人的形态、运动方式和工作效率。对于青少年机器人爱好者来说&#xff0c;了解机械结构的基础知识&#xff0c;掌…

分布式主键ID生成策略

小程序搜索“ 源码轻舟 ”后续将推出算法和面试模块 坚持学习&#xff0c;好文每日送达&#xff01; 业务系统对分布式ID的要求 唯一性&#xff1a;在分布式系统中&#xff0c;每个节点都需要生成唯一的标识符来确保数据的唯一性。传统的单点生成ID方式无法满足分布式环境下的…

音视频技术开发周刊 | 300

每周一期&#xff0c;纵览音视频技术领域的干货。 新闻投稿&#xff1a;contributelivevideostack.com。 著名数据和AI企业Databricks&#xff0c;收购类ChatGPT开源平台MosaicML 6月27日&#xff0c;Databricks在官网宣布&#xff0c;以13亿美元&#xff08;约94亿元&#xff…

浅析便捷生活的新选择——抖音本地服务

抖音是一款风靡全球的短视频分享平台&#xff0c;其本地服务功能的发展也逐渐引起了广泛关注。本地服务是指抖音平台上的用户可以通过平台直接查找并使用周边的各种服务&#xff0c;比如美食外卖、快递配送、家政服务等。本地服务的发展对用户和商家都带来了很多便利和机遇。 首…

Spring Boot 中的 Spring Cloud Hystrix 是什么,原理,如何使用

Spring Boot 中的 Spring Cloud Hystrix 是什么&#xff0c;原理&#xff0c;如何使用 简介 在分布式系统中&#xff0c;服务之间的调用是不可避免的。但是&#xff0c;当一个服务调用另一个服务时&#xff0c;如果被调用的服务出现了故障或者延迟&#xff0c;那么调用者也会…

发布/上传Jar包到Maven中央仓库

1.注册Sonatype账号 2.项目申请&#xff0c;创建工单 2.1回复 groupId 域名 可以使用github&#xff0c; io.github.账号 创建工单根据评论回复&#xff0c;需要创建临时仓库&#xff0c;验证账户所有权。 3.gpg4win 地址&#xff1a;https://www.gpg4win.org/download.html &…

电子时钟制作(瑞萨RA)(5)----定时器驱动数码管

概述 要想让每个数码管显示不同的数字&#xff0c;但是数码管必须依次地被持续驱动&#xff0c;数码管之间的刷新速度应该足够快&#xff0c;这样就看不出来数码管之间在闪烁。刷新频率可以设置为2ms刷新一次&#xff0c;这样人眼就看不出闪烁了。 硬件准备 首先需要准备一个…

2011年全国硕士研究生入学统一考试管理类专业学位联考逻辑试题——纯享题目版

&#x1f3e0;个人主页&#xff1a;fo安方的博客✨ &#x1f482;个人简历&#xff1a;大家好&#xff0c;我是fo安方&#xff0c;考取过HCIE Cloud Computing、CCIE Security、CISP、RHCE、CCNP RS、PEST 3等证书。&#x1f433; &#x1f495;兴趣爱好&#xff1a;b站天天刷&…

生态环境脆弱性评价模型构建、时空格局演变分析与RSEI 指数的生态质量评价及拓展

近年来&#xff0c;国内外学者在生态系统的敏感性、适应能力和潜在影响等方面开展了大量的生态脆弱性研究&#xff0c;他们普遍将生态脆弱性概念与农牧交错带、喀斯特地区、黄土高原区、流域、城市等相结合&#xff0c;评价不同类型研究区的生态脆弱特征&#xff0c;其研究内容…

C++ STL --List

1. list的介绍及使用 1.1 list的介绍 1. list 是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代。 2. list 的底层是双向链表结构&#xff0c;双向链表中每个元素存储在互不相关的独立节点中&#xff0c;在节点中通过指针指…

云原生之深入解析MySQL在K8S环境中部署与监控

一、准备工作 MySQL是一个关系型数据库管理系统&#xff0c;由瑞典 MySQL AB 公司开发&#xff0c;属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一&#xff0c;在 WEB 应用方面&#xff0c;MySQL 是最好的 RDBMS (Relational Database Management System&am…

Spring Boot的Maven插件Spring Boot Maven plugin详解

1.Spring Boot的Maven插件Spring Boot Maven plugin详解 2.Maven插件之git-commit-id-plugin

vue3+ts+elementui制作精美的课表

使用vue3tselementui 如何制作出精美的课表呢&#xff0c; 最终效果图如下: 直接上代码&#xff1a; 这里直接把封装成一个课表的组件&#xff1a; <script setup lang"ts"> import { ref, watch, onMounted } from "vue"; import IconText from …

Fortinet FortiOS 7.4.0 (FortiGate VM deployment Images) - 混合架构防火墙

Fortinet FortiOS 7.4.0 (FortiGate VM deployment Images) - 混合架构防火墙 下一代防火墙 (NGFW)、虚拟化 NGFW 和云原生防火墙 请访问原文链接&#xff1a;https://sysin.org/blog/fortios-7/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&…

MySQL表的增删改查(数据库系列3)

目录 前言&#xff1a; 1.CRUD的解释 2.表的基本操作 2.1查看数据表 2.2创建表 2.3查看指定表的表结构 2.4删除表 2.5注释 3.新增&#xff08;Create&#xff09; 4.查询&#xff08;Retrieve&#xff09; 4.1全列查询 4.2指定列查询 4.3查询字段为表达式 4.4指定…

Linux_Linux基本指令(1)

目录 一、ls指令 二、pwd命令 三、cd指令 四、touch指令 五、mkdir指令 六、rmdir指令&&rm指令 一、ls指令 语法&#xff1a;ls [选项][目录或文件] 对于目录&#xff0c;ls指令是用来列出目录下的所有子目录与文件。对于文件&#xff0c;则是列出文件名及其他信…

zabbix 安装 踩坑记录与解决方案

博主首次安装 zabbix 时&#xff0c;出现了一些错误&#xff0c;特此记录一下&#xff0c;希望帮助到一些 Zabbix freshman. 参考其他博客安装 zabbix 时&#xff0c;运行到如下command 安装zabbix 相关组件出现如下Error: apt installzabbix-server-mysql zabbix-frontend-p…

154个Bug!

持续测试了一个月的H5项目&#xff0c;终于迎来了上线日&#xff0c;在测试H5的过程中&#xff0c;遇到了一些坑&#xff0c;积累了些许经验&#xff0c;想着分享一下&#xff0c;希望对大家有所启发。 主要从以下一个方面展开&#xff1a; 一、项目背景 二、测试环境准备 三…

专项练习18

目录 一、选择题 1、下列选项中&#xff0c;&#xff08;&#xff09;不是网页中的事件 2、下面有关浏览器中使用js跨域获取数据的描述&#xff0c;说法错误的是&#xff1f; 3、请问以下程序的输出是 4、以下哪一项不属于浏览器Response Headers字段&#xff1a; 一、选择题 …