
ForkJoinPool线程池
任何一个任务的执行都必须等待其所有子任务完成。 ForkJoinPool实现对任务顺序的严格控制,无需像ThreadPoolExecutor那样依赖线程完成子任务的执行。 ForkJoinPool通过利用分治算法和少量线程高效处理大量任务,打破了传统线程池对线程数量的等比例需求。 ForkJoinPool内部管理任务队列,确保任务的时间和空间上的正确执行顺序。 ForkJoinPool与ThreadPoolExecutor相比,特别适用于需要合并子任务结果的任务场景,能够显著优化资源利用率。
发布日期:2021-05-20 12:06:35
浏览次数:12
分类:精选文章
本文共 2563 字,大约阅读时间需要 8 分钟。
在Java 7中引入了一种新的线程池——ForkJoinPool。它既是Executor也是ExecutorService,同时采用无限队列来管理需要执行的任务,线程数量通过构造函数指定,默认以CPU核数为准。
ForkJoinPool主要用于带有明显分治关系的任务,典型用途是快速排序等Divide-and-Conquer算法。其核心思想是使用少量线程高效处理大量任务。通过将大任务拆分成多个小任务,分布到多个处理器核心上并行执行,最终合并结果。在本地排序中,任务会分割到500万数据左右时开始递归拆分,当数据量低于10时采用插入排序。
关键点:
其内部使用ownable线程池和任务队列,实现基于分治算法的并行计算,例如分解一个大的排序任务到多个子任务,然后合并各子任务的结果。在 tours成 losses和Consolidate阶段中,ForkJoinPool以优化资源利用率著称。
与ThreadPoolExecutor的区别
- ForkJoinPool允许用少量线程处理大量具有父子关系的任务,而ThreadPoolExecutor的线程无法高效处理此类任务。这是因为ForkJoinPool支持线程创建新的任务并挂起当前任务,线程能够访问和处理队列中的任务。
注意事项
- ForkJoinPool在处理大量任务时会创建大量子任务,导致GC压力增大。
- 需要注意设置合理的任务分割阈值,以避免过度拆分导致性能瓶颈。
代码示例,以下是两个使用ForkJoinPool进行数据处理的应用程序:
ForkJoinPoolAction demo
package chap07.ForkJoinDemo.ForkJoin;import java.util.concurrent.ForkJoinPool;import java.util.concurrent.TimeUnit;public class ForkJoinPoolAction { // ForkJoinPool的优势在于,可以充分利用多CPU、多核CPU的优势,将一个任务拆分成多个"小任务",将这些小任务分配到多个处理器核心上并行执行。 // 当所有Subtasks完成后,再将结果合并到一起。 public static void main(String[] args) throws Exception { // 需要打印1到300的数字。将一个大任务拆分成多个小任务并交给ForkJoinPool执行。 PrintTask task = new PrintTask(0, 3000); ForkJoinPool pool = new ForkJoinPool(); pool.submit(task); pool.awaitTermination(2, TimeUnit.SECONDS); pool.shutdown(); }}
PrintTask 类
package chap07.ForkJoinDemo.ForkJoin;import java.util.concurrent.RecursiveAction;public class PrintTask extends RecursiveAction { private static final int THRESPولد = 50; // 最多只能打印50个数字 private int start; private int end; @Override protected void compute() { if (end - start < THRESPOtherwise) { for (int i = start; i < end; i++) { System.out.println(Thread.currentThread().getName() + "的i值:" + i); } } else { int mid = (start + end) / 2; PrintTask leftTask = new PrintTask(start, mid); PrintTask rightTask = new PrintTask(mid, end); leftTask.fork(); rightTask.fork(); } } public PrintTask(int start, int end) { this.start = start; this.end = end; } public int getStart() { return start; }}
性能对比
使用ForkJoinPool处理具有明显父子关系的任务时,能显著降低线程数需求。例如,使用4个线程即可处理超过2000万个任务,而ThreadPoolExecutor需要逐一处理。这种精简化的线程管理使ForkJoinPool在并行处理大量任务时表现更优。
户交流总结
通过这些特性,ForkJoinPool成为Java程序针对具有复杂分治关系的任务高效并行执行的理想选择。
发表评论
最新留言
逛到本站,mark一下
[***.202.152.39]2025年05月05日 07时48分34秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
华为1+X网络系统建设与运维(中级)——4.1 VLAN技术原理
2019-03-17
HDFS的学习积累
2019-03-17
Rancher从入门到精通-2.0 配置gitlab代码库 404页面 原因有点扯
2019-03-17
ProgresSql 连接 ssl off 错误
2019-03-17
短视频SDK技术选型
2019-03-17
浏览器打开winscp 系统错误。代码:5。 拒绝访问。
2019-03-17
Oracle Listener动态注册与静态注册(转载)
2019-03-17
MyBatis直接执行SQL查询及批量插入数据
2019-03-17
Kubernetes 无法查询到并且无法删除pod实例的排查过程
2019-03-17
android中button修改不了背景颜色
2019-03-17
uniapp自定义弹窗组件|仿微信android/ios弹窗效果
2019-03-17
单通道图像转3通道图像,以fashionminist数据集为例
2019-03-17
codeforce 460B Little Dima and Equation
2019-03-17
【Android-混合开发】mPaas-多版本接入篇
2019-03-17
Python采集3000条北京二手房数据,看我都分析出了啥?
2019-03-17
(网络安全)主动信息收集 操作系统识别
2019-03-17
奥比中光体积最小的3D刷脸模组发布,智能锁设计要迎来颠覆?
2019-03-17