在JAVA7之前,并行处理数据非常麻烦。第一,你得明确把包含数据的数据结构分成若干份。第二,你要将每个子部分分配给一个独立的线程。第三,你要在恰当的时候对它们进行同步避免不希望的竞争条件,等待所有线程完成,最后把这些部分结果合并起来。在Java 7引入了分支/合并框架,让这些操作更稳定、更不容易出错。
分支/合并框架的目的是以递归的方式将可以并行的任务拆分为更小的任务,然后将每个子任务的结果合并起来生成整体结果。要把子任务提交到ForkJoinPool必须创建RecursiveTask<R>的子类。需要实现它唯一的抽象方法 protected abstract R compute(); 在这个方法中定义了将任务拆分成子任务的逻辑,以及无法拆分时生成单个子任务结果的逻辑。
计算1到10000000的和
/** * Desc:Fork/Join框架的目的是以递归方式将可以并行的任务拆分为更小的任务,然后将每个子任务的结果合并起来生成一个整体结果。 * 要把任务提交到ForkJoinPool必须创建RecursiveTask<T> 的一个子类 * * @author wei.zw * @since 2016年7月6日 下午9:27:56 * @version v 0.1 */ public class ForkJoinSumCalculator extends RecursiveTask<Long> { /** */ private static final long serialVersionUID = -8013303660374621470L; private final long[] numbers; private final int start; private final int end; private static final long THRESHOLD = 1000; /** * @param numbers * @param start * @param end */ public ForkJoinSumCalculator(long[] numbers, int start, int end) { super(); this.numbers = numbers; this.start = start; this.end = end; } /** * @param numbers */ public ForkJoinSumCalculator(long[] numbers) { super(); this.numbers = numbers; this.start = 0; this.end = numbers.length; } /** * @see java.util.concurrent.RecursiveTask#compute() */ @Override protected Long compute() { int length = end - start; if (length <= THRESHOLD) { return computeSequentially(); } ForkJoinSumCalculator leftTask = new ForkJoinSumCalculator(numbers, start, start + length / 2); leftTask.fork(); ForkJoinSumCalculator rightTask = new ForkJoinSumCalculator(numbers, start + length / 2, end); rightTask.fork(); Long rightResult = 0L; try { rightResult = rightTask.get(); } catch (Exception e) { } Long leftResult = leftTask.join(); return leftResult + rightResult; } /** * * @return * @author wei.zw */ private Long computeSequentially() { long sum = 0; for (int i = start; i < end; i++) { sum += numbers[i]; } return sum; } public static void main(String[] args) { long[] numbers = LongStream.rangeClosed(1, 10000000).toArray(); long start = System.currentTimeMillis(); System.out.println(new ForkJoinPool().invoke(new ForkJoinSumCalculator(numbers)) + " 耗时:" + (System.currentTimeMillis() - start)); } }
结果是:50000005000000 耗时:37
优化后的
/** * @see java.util.concurrent.RecursiveTask#compute() */ @Override protected Long compute() { int length = end - start; if (length <= THRESHOLD) { return computeSequentially(); } ForkJoinSumCalculator leftTask = new ForkJoinSumCalculator(numbers, start, start + length / 2); leftTask.fork(); ForkJoinSumCalculator rightTask = new ForkJoinSumCalculator(numbers, start + length / 2, end); Long rightResult = rightTask.compute(); Long leftResult = leftTask.join(); return leftResult + rightResult; }
计算结果是:50000005000000 耗时:25
使用Fork/Join框架的最佳做法:
- 对一个任务调用join方法会阻塞调用方,直到该任务作出结果。因此,又必须要在两个子任务的计算都开始之后再调用它。
- 不应该在RecursiveTask内部使用ForkJoinPool的invoke方法,应该直接调用compute或者fork方法
- 对子任务调用fork方法可以将这个子任务排进ForkJoinPool。同时对左右两边的子任务都调用似乎很自然,但是这样做的效率比直接对其中一个调用compute方法低。这样做可以为其中一个子任务重用同一线程,从而避免在线程池中多分配一个任务造成的开销。
相关推荐
主要介绍了Java线程池ForkJoinPool实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
HTML基础学习示例代码HTML基础学习示例代码HTML基础学习示例代码 HTML基础学习示例代码HTML基础学习示例代码HTML基础学习示例代码 HTML基础学习示例代码HTML基础学习示例代码HTML基础学习示例代码 HTML基础学习示例...
ansible最佳学习示例
ASP.NET 学习 示例 源代码 下载ASP.NET 学习 示例 源代码 下载ASP.NET 学习 示例 源代码 下载ASP.NET 学习 示例 源代码 下载ASP.NET 学习 示例 源代码 下载ASP.NET 学习 示例 源代码 下载ASP.NET 学习 示例 源代码 ...
自己的学习示例文档
多示例学习与多标记学习的研究,在工作的应用场景中很有帮助
Java语言学习示例代码Java语言学习示例代码Java语言学习示例代码Java语言学习示例代码Java语言学习示例代码Java语言学习示例代码Java语言学习示例代码Java语言学习示例代码Java语言学习示例代码Java语言学习示例代码...
Spring Cloud Contract 学习 示例 Spring Cloud Contract 学习 示例 Spring Cloud Contract 学习 示例 Spring Cloud Contract 学习 示例
人工智能学习示例文件
学习html时的笔记、示例学习html时的笔记、示例学习html时的笔记、示例 学习html时的笔记、示例学习html时的笔记、示例学习html时的笔记、示例 学习html时的笔记、示例学习html时的笔记、示例学习html时的笔记、示例...
学习Java基础的示例代码的集合,包括基本语言、GUI、网络编程等等
等线程示例学习等线程示例学习等线程示例学习等线程示例学习等线程示例学习等线程示例学习
一些学习sql语句的例句。包括存储过程、游标、自定义函数等各种高难度sql语句写法。
autojs超多代码 教程学习 示例
机器学习实战示例代码,附书籍地址 所有章节示例代码(KNN treePlotter bayes logRegres svmMLiA等)
机器学习的很多示例代码,包括模型估计与优化的房屋价格预测、监督学习、集成学习、强化学习、神经网络的内容示例应用示例
spark机器学习示例代码 machine learning with spark
jQuery学习示例 大全 最新
C# HELLOW示例,YIELD示例,XML注释示例,不安全代码示例,OLEDB示例,版本控制示例,线程示例,数组示例,属性示例,可空类型示例,事件示例,代理示例,类库示例,COM平台示例,安全性示例,结构示例,特性示例,运算符重载示例,命...