一 点睛

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介绍相关推荐

  1. 线程池之ForkJoinPool

    概述 ForkJoinPool分支/合并框架,就是在必要的情况下,将一个大任务拆分(fork)成若干个小任务(拆到不能再拆为止),再将一个个的小任务运算的结果进行Join汇总. ThreadPool与 ...

  2. 40个问题让你快速掌握Java多线程的精髓

    本文分享自华为云社区<对Java多线程的用法感到一头乱麻?40个问题让你快速掌握多线程的精髓>,原文作者:breakDraw . 多线程可以理解为在同一个程序中能够同时运行多个不同的线程来 ...

  3. 介绍一下 ForkJoinPool

    介绍一下 ForkJoinPool ForkJoinPool 是 JDK1.7 开始提供的线程池.为了解决 CPU 负载不均衡的问题.如某个较大的任务,被一个线程去执行,而其他线程处于空闲状态. Fo ...

  4. Fork/Join 框架介绍

    参考:https://www.infoq.cn/article/fork-join-introduction 1. 什么是 Fork/Join 框架 Fork/Join 框架是 Java7 提供了的一 ...

  5. java中ThreadPool的介绍和使用

    文章目录 Thread Pool简介 Executors, Executor 和 ExecutorService ThreadPoolExecutor ScheduledThreadPoolExecu ...

  6. 聊聊并发(八)——Fork/Join框架介绍

    转载自   聊聊并发(八)--Fork/Join框架介绍 1. 什么是Fork/Join框架 Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务, ...

  7. scheduledexecutorservice 的使用_java中ThreadPool的介绍和使用

    Thread Pool简介 在Java中,threads是和系统的threads相对应的,用来处理一系列的系统资源.不管在windows和linux下面,能开启的线程个数都是有限的,如果你在java程 ...

  8. 多线程 ForkJoinPool

    背景:ForkJoinPool的优势在于,可以充分利用多cpu,多核cpu的优势,把一个任务拆分成多个"小任务",把多个"小任务"放到多个处理器核心上并行执行: ...

  9. ForkJoinPool的使用及基本原理

    目录 1.ForkJoinPool是什么 1.1 分治法 1.2 工作窃取(work-stealing,中文又译作偷工减料,也有道理) 2.简单使用 2.1 不带返回值的计算 2.2 带返回值的计算 ...

最新文章

  1. Netty详解(六):Netty 编解码技术
  2. 2.4g 无线键鼠对码软件_无线路由器的2.4G和5G同时开速度有影响吗?
  3. 【深度学习】在PyTorch中使用 LSTM 自动编码器进行时间序列异常检测
  4. JavaScript JSON操作
  5. 数据中心两种常用流量模型运用mininet的实现
  6. python Pillow 的简单案例
  7. 抽象类和接口有哪些共同点和区别
  8. Spring Cloud Alibaba Sentinel之热点参数限流篇
  9. 【21天python打卡】第15天 python经典案例(1)
  10. mysql directx repair_[MySQL]快速解决is marked as crashed and should be repaired故障
  11. 用Python网络爬虫来抓取网易云音乐歌词
  12. 2015-5-23PDF的下载链接
  13. Mac使用手册:如何检查 Mac 或 iOS 设备仍在保修范围内
  14. 检查日期是否为节假日api
  15. vue的entries和nextTick
  16. Python编写函数,计算某个员工的奖金发放额度,要求输入员工的营业额,输出对应的奖金总额
  17. SAP PS 第12节 PS常用BAPI调用示例
  18. WIN10 + Tensorflow1.12 + Cmake编译 + Bazel编译
  19. tomcat 7.0
  20. 2018X-NUCA------auth2

热门文章

  1. Mybase7延长试用期
  2. 阅读 | 《娱乐至死》笔记 | Part1
  3. [华为 HCNA ] VLAN的介绍和划分
  4. 杰理之汤姆猫录音变声功能参考【篇】
  5. Unity学习笔记-I2 localization
  6. 个人整理可编辑PDF值得一读的电子书大全(持续更新)
  7. onenote如何删除笔记本
  8. python相关库快速下载
  9. 我的学习笔记002--asp.net中的路径mxx
  10. JS 中 Object 的 keys 是无序的吗?