ForkJoinPool介绍
一 点睛
Java7 提供了ForkJoinPool来支持将一个任务拆分成多个“小任务”并行计算,再把多个“小任务”的结果合并成总的计算结果。
ForkJoinPool是ExecutorService的实现类,因此是一种特殊的线程池。
使用方法:创建了ForkJoinPool实例之后,就可以调用ForkJoinPool的submit(ForkJoinTask<T> task) 或invoke(ForkJoinTask<T> task)方法来执行指定任务了。
其中ForkJoinTask代表一个可以并行、合并的任务。ForkJoinTask是一个抽象类,它还有两个抽象子类:RecusiveAction和RecusiveTask。其中RecusiveTask代表有返回值的任务,而RecusiveAction代表没有返回值的任务。
下面的UML类图显示了ForkJoinPool、ForkJoinTask之间的关系:
二 无返回值实战——通过多线程分多个小任务进行打印数据
1 代码
import java.util.concurrent.*;
// 继承RecursiveAction来实现"可分解"的任务
class PrintTask extends RecursiveAction
{// 每个“小任务”只最多只打印50个数private static final int THRESHOLD = 50;private int start;private int end;// 打印从start到end的任务public PrintTask(int start, int end){this.start = start;this.end = end;}@Overrideprotected void compute(){// 当end与start之间的差小于THRESHOLD时,开始打印if(end - start < THRESHOLD){for (int i = start ; i < end ; i++ ){System.out.println(Thread.currentThread().getName()+ "的i值:" + i);}}else{// 如果当end与start之间的差大于THRESHOLD时,即要打印的数超过50个// 将大任务分解成两个小任务。int middle = (start + end) / 2;PrintTask left = new PrintTask(start, middle);PrintTask right = new PrintTask(middle, end);// 并行执行两个“小任务”left.fork();right.fork();}}
}
public class ForkJoinPoolTest
{public static void main(String[] args)throws Exception{ForkJoinPool pool = new ForkJoinPool();// 提交可分解的PrintTask任务pool.submit(new PrintTask(0 , 300));pool.awaitTermination(2, TimeUnit.SECONDS);// 关闭线程池pool.shutdown();}
}
2 运行
ForkJoinPool-1-worker-0的i值:183
ForkJoinPool-1-worker-0的i值:184
ForkJoinPool-1-worker-0的i值:185
ForkJoinPool-1-worker-0的i值:186
ForkJoinPool-1-worker-3的i值:192
ForkJoinPool-1-worker-3的i值:193
ForkJoinPool-1-worker-3的i值:194
ForkJoinPool-1-worker-3的i值:195
......
ForkJoinPool-1-worker-3的i值:220
ForkJoinPool-1-worker-3的i值:221
ForkJoinPool-1-worker-3的i值:222
ForkJoinPool-1-worker-3的i值:223
ForkJoinPool-1-worker-3的i值:224
ForkJoinPool-1-worker-2的i值:90
ForkJoinPool-1-worker-2的i值:91
ForkJoinPool-1-worker-2的i值:92
ForkJoinPool-1-worker-2的i值:93
ForkJoinPool-1-worker-2的i值:94
......
ForkJoinPool-1-worker-2的i值:108
ForkJoinPool-1-worker-2的i值:109
ForkJoinPool-1-worker-2的i值:110
ForkJoinPool-1-worker-2的i值:111
ForkJoinPool-1-worker-1的i值:249
ForkJoinPool-1-worker-1的i值:250
ForkJoinPool-1-worker-1的i值:251
ForkJoinPool-1-worker-1的i值:252
ForkJoinPool-1-worker-1的i值:253
3 结果
从结果来看,程序启动了4个线程来执行这个打印任务——这是因为运行计算机有4个CPU。下面是CPU运行图。
三 返回结果集——通过多线程分多个小任务进行数据累加
1 代码
import java.util.concurrent.*;
import java.util.*;// 继承RecursiveTask来实现"可分解"的任务
class CalTask extends RecursiveTask<Integer>
{// 每个“小任务”只最多只累加20个数private static final int THRESHOLD = 20;private int arr[];private int start;private int end;// 累加从start到end的数组元素public CalTask(int[] arr , int start, int end){this.arr = arr;this.start = start;this.end = end;}@Overrideprotected Integer compute(){int sum = 0;// 当end与start之间的差小于THRESHOLD时,开始进行实际累加if(end - start < THRESHOLD){for (int i = start ; i < end ; i++ ){sum += arr[i];}return sum;}else{// 如果当end与start之间的差大于THRESHOLD时,即要累加的数超过20个时// 将大任务分解成两个小任务。int middle = (start + end) / 2;CalTask left = new CalTask(arr , start, middle);CalTask right = new CalTask(arr , middle, end);// 并行执行两个“小任务”left.fork();right.fork();// 把两个“小任务”累加的结果合并起来return left.join() + right.join(); // ①}}
}
public class Sum
{public static void main(String[] args)throws Exception{int[] arr = new int[100];Random rand = new Random();int total = 0;// 初始化100个数字元素for (int i = 0 , len = arr.length; i < len ; i++ ){int tmp = rand.nextInt(20);// 对数组元素赋值,并将数组元素的值添加到sum总和中。total += (arr[i] = tmp);}System.out.println(total);// 创建一个通用池ForkJoinPool pool = ForkJoinPool.commonPool();// 提交可分解的CalTask任务Future<Integer> future = pool.submit(new CalTask(arr , 0 , arr.length));System.out.println(future.get());// 关闭线程池pool.shutdown();}
}
2 运行
917
917
3 说明
运行上面的程序,将可以看到通过CalTask计算出来的总和,与初始化数组元素时统计出来的总和总是相等的。
四 参考
https://blog.csdn.net/qq_27026603/article/details/82049741
ForkJoinPool介绍相关推荐
- 线程池之ForkJoinPool
概述 ForkJoinPool分支/合并框架,就是在必要的情况下,将一个大任务拆分(fork)成若干个小任务(拆到不能再拆为止),再将一个个的小任务运算的结果进行Join汇总. ThreadPool与 ...
- 40个问题让你快速掌握Java多线程的精髓
本文分享自华为云社区<对Java多线程的用法感到一头乱麻?40个问题让你快速掌握多线程的精髓>,原文作者:breakDraw . 多线程可以理解为在同一个程序中能够同时运行多个不同的线程来 ...
- 介绍一下 ForkJoinPool
介绍一下 ForkJoinPool ForkJoinPool 是 JDK1.7 开始提供的线程池.为了解决 CPU 负载不均衡的问题.如某个较大的任务,被一个线程去执行,而其他线程处于空闲状态. Fo ...
- Fork/Join 框架介绍
参考:https://www.infoq.cn/article/fork-join-introduction 1. 什么是 Fork/Join 框架 Fork/Join 框架是 Java7 提供了的一 ...
- java中ThreadPool的介绍和使用
文章目录 Thread Pool简介 Executors, Executor 和 ExecutorService ThreadPoolExecutor ScheduledThreadPoolExecu ...
- 聊聊并发(八)——Fork/Join框架介绍
转载自 聊聊并发(八)--Fork/Join框架介绍 1. 什么是Fork/Join框架 Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务, ...
- scheduledexecutorservice 的使用_java中ThreadPool的介绍和使用
Thread Pool简介 在Java中,threads是和系统的threads相对应的,用来处理一系列的系统资源.不管在windows和linux下面,能开启的线程个数都是有限的,如果你在java程 ...
- 多线程 ForkJoinPool
背景:ForkJoinPool的优势在于,可以充分利用多cpu,多核cpu的优势,把一个任务拆分成多个"小任务",把多个"小任务"放到多个处理器核心上并行执行: ...
- ForkJoinPool的使用及基本原理
目录 1.ForkJoinPool是什么 1.1 分治法 1.2 工作窃取(work-stealing,中文又译作偷工减料,也有道理) 2.简单使用 2.1 不带返回值的计算 2.2 带返回值的计算 ...
最新文章
- Netty详解(六):Netty 编解码技术
- 2.4g 无线键鼠对码软件_无线路由器的2.4G和5G同时开速度有影响吗?
- 【深度学习】在PyTorch中使用 LSTM 自动编码器进行时间序列异常检测
- JavaScript JSON操作
- 数据中心两种常用流量模型运用mininet的实现
- python Pillow 的简单案例
- 抽象类和接口有哪些共同点和区别
- Spring Cloud Alibaba Sentinel之热点参数限流篇
- 【21天python打卡】第15天 python经典案例(1)
- mysql directx repair_[MySQL]快速解决is marked as crashed and should be repaired故障
- 用Python网络爬虫来抓取网易云音乐歌词
- 2015-5-23PDF的下载链接
- Mac使用手册:如何检查 Mac 或 iOS 设备仍在保修范围内
- 检查日期是否为节假日api
- vue的entries和nextTick
- Python编写函数,计算某个员工的奖金发放额度,要求输入员工的营业额,输出对应的奖金总额
- SAP PS 第12节 PS常用BAPI调用示例
- WIN10 + Tensorflow1.12 + Cmake编译 + Bazel编译
- tomcat 7.0
- 2018X-NUCA------auth2