ForkJoinPool 学习示例

    

     在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()*/@Overrideprotected 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()*/@Overrideprotected 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方法低。这样做可以为其中一个子任务重用同一线程,从而避免在线程池中多分配一个任务造成的开销。

看完了基本示例,在分析一下源码;首先看一下RecursiveTask,通过名称可以知道这是一个递归Task.源码很简单

public abstract class RecursiveTask<V> extends ForkJoinTask<V> {private static final long serialVersionUID = 5232453952276485270L;//计算结果V result;//抽象的计算方法protected abstract V compute();//获取计算结果public final V getRawResult() {return result;}//设置计算结果protected final void setRawResult(V value) {result = value;}//执行计算protected final boolean exec() {result = compute();return true;}}

 RecursiveTask源码看完以后,继续分析ForkJoinTask

 

  

 

转载于:https://www.cnblogs.com/wei-zw/p/8797732.html

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

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

相关文章

python深入_Python深入(上)

作者&#xff1a;Vamei 出处&#xff1a;http://www.cnblogs.com/vamei 欢迎转载&#xff0c;也请保留这段声明。谢谢&#xff01;到现在为止&#xff0c;Python学习已经可以告一段落。下面的部分&#xff0c;我想讨论Python的高级语法和底层实现。这一部分的内容并不是使用Pyt…

06_JS对象

JS对象 创建对象 构造函数&#xff1a;var obj new Object()对象字面量&#xff1a;var obj {}; 不同&#xff1a;对象字面量可以在创建的同时为对象设置属性&#xff0c;最后一个属性后面不要加逗号 对象操作 添加属性&#xff1a;对象名.新属性名 值修改属性&#xf…

BZOJ4107 : [Wf2015]Asteroids

首先将速度相减&#xff0c;变成A在动而B不动&#xff0c;若速度为0则显然永远不会相交。 枚举A的每个点以及B的每条线段&#xff0c;计算这三个点共线的时刻。 将时刻排序&#xff0c;对于每个区间进行三分&#xff0c;用半平面交计算相交面积。 注意特判相交面积为0但是存在交…

Web Service 性能测试工具比较

背景 希望选择一款Web Service性能测试工具&#xff0c;能真实模拟大量用户访问网站时的请求&#xff0c;从而获取服务器当前的请求处理能力&#xff08;请求数/秒&#xff09;。以微信服务器为例&#xff0c;每个用户用独立的登录token&#xff0c;做各种操作&#xff0c;比如…

python中的常量是什么意思_第14p,Python中的常量与注释。

大家好&#xff0c;我是杨数Tos&#xff0c;这是《从零基础到大神》系列课程的第14篇文章&#xff0c;第二阶段的课程&#xff1a;Python基础知识&#xff1a;常量与注释。学习本课程&#xff0c;建议先看一遍&#xff1a;【计算机基础知识】课程。一、Python中的常量1、什么是…

07_JS函数

JS函数 函数声明 使用构造函数 var fun new Function();使用关键字 function 函数名(形参){// 函数体 }匿名函数 var fun1 function(){name "fun1" }函数参数 实参&#xff0c;形参都可以是任意数据类型&#xff0c;浏览器执行时不会检查实参类型和数量&…

cocoapods的安装(这真是一个神奇的东西,每次安装的方法都不一样,而且很容易出现各种各样的错误)...

文章开始之前&#xff0c;建议安装一个显示网速的插件&#xff0c;不然你不知道到底有没有下载&#xff0c;也让生活有一点盼头 1.因为众所周知的原因&#xff08;我dang的行为真的是让人失望&#xff09;&#xff0c;先更换一下ruby镜像源 $ gem sources --remove https://rub…

转】MyEclipse使用总结——在MyEclipse中设置jsp页面为默认utf-8编码

原博文出自于&#xff1a;http://www.cnblogs.com/xdp-gacl/p/3496161.html        感谢&#xff01; 在MyEclispe中创建Jsp页面&#xff0c;Jsp页面的默认编码是“ISO-8859-1”&#xff0c;如下图所示&#xff1a; 在这种编码下编写中文是没有办法保存Jsp页面的&#…

sum怎么用python_python sum()函数和.sum(axis=0)函数的使用

参考&#xff1a;《Machine Learning in Action》第二章#####################################################################sum函数&#xff1a;sum()函数是内建函数help(sum)函数功能&#xff1a;返回一个数字序列(非字符串)的和&#xff0c;并加上参数start的值(默认为…

08_JS工厂方法和构造函数

工厂方法和构造函数 工厂方法 工厂方法用来批量产生对象 function CreatCar(name,prase){// new 一个对象var obj new Object();obj.name name;obj.parse prase;obj.print function(){console.log(this.name " : " this.parse)};// 返回对象return obj; };va…

华为机试题【10】-求数字基root

题目描述&#xff1a; 求整数的Root:给定正整数,求每位数字之和;如果和不是一位数,则重复; 输入&#xff1a;输入任意一个或多个整数 输出&#xff1a;输出各位数字之和,直到和为个位数为止(输入异常,则返回-1)&#xff0c;多行&#xff0c;每行对应一个输入数据的结果。 样例…

国内开源镜像站

搜狐开源镜像站&#xff1a;http://mirrors.sohu.com/ 网易开源镜像站&#xff1a;http://mirrors.163.com/开源中国&#xff1a;http://mirrors.oschina.net/首都在线科技股份有限公司&#xff1a;http://mirrors.yun-idc.com/阿里云开源镜像&#xff1a;http://mirrors.aliyu…

python update skeleton 不自动_python编程笔记(1)-数据类型

断断续续学了一些&#xff0c;但是后边一直没有使用&#xff0c;就又忘记了。为了缩短学习周期&#xff0c;这次学习的方法&#xff1a;先学主要框架&#xff08;数据类型、条件、循环、函数、类、numpy、pandas、sklearn&#xff09;&#xff0c;后期直接看朋友code 实操了&am…

09_JS原型对象

原型对象 在构造函数中&#xff0c;同一类相同的方法可以直接写在构造函数里&#xff0c;但这样每实例化一个对象都会产生一个新的该方法&#xff0c;但其实这个方法都是一样的&#xff0c;这样会浪费大量空间&#xff0c;另外&#xff0c;可以将相同的方法写在构造函数外&…

[改善Java代码]非稳定排序推荐使用List

我们知道Set与List的最大区别就是Set中的元素不可以重复&#xff08;这个重复指的equals方法的返回值相等&#xff09;&#xff0c;其他方面则没有太大的区别了&#xff0c;在Set的实现类中有一个比较常用的类需要了解一下&#xff1a;TreeSet&#xff0c;该类实现了类默认排序…

如何访问另一台电脑的共享文件夹_如何远程控制另一台电脑

在工作中&#xff0c;我们时常需要远程控制一下另一台电脑&#xff0c;如果这两台计算机在局域网内可以通过远程桌面轻松实现&#xff0c;如果这两台计算机不在局域网内则通常需要借助第三方软件来实现。远程桌面使用分三步&#xff1a;1、被控制端要开启远程桌面功能&#xff…

10_JS数组

JS 数组 以索引为键的对象&#xff0c;性能高于对象 创建 new Array() var arr Array() for(var i 0;i<5;i){arr[i] i; };var arr Array(1,2,3,4,5,6)数组字面量 var arr [2,3,4,5,6,7,8];不同&#xff1a;传入一个整数时&#xff0c;new把这个数当作数组长度&…

微软Hololens学院教程- Holograms 101: Introduction with Device【微软教程已经更新,本文是老版本】...

这是老版本的教程&#xff0c;为了不耽误大家的时间&#xff0c;请直接看原文&#xff0c;本文仅供参考哦&#xff01;原文链接&#xff1a;https://developer.microsoft.com/EN-US/WINDOWS/HOLOGRAPHIC/holograms_101 这篇文章将通过一个完整的实例来了解设备的核心特性&#…

python seaborn boxplot_python - 如何将文本框添加到Seaborn Boxplot? - 堆栈内存溢出

我试图在框图中插入一个文本框&#xff0c;但是出了点问题。 让我们先绘制箱线图&#xff1a;import pandas as pdimport matplotlib.pyplot as pltimport seaborn as sbdf_data pd.read_hdf(data.h5, keyfdf_data)##print(df_data)fig, (ax1, ax2) plt.subplots(1,2,gridspe…

JS_11正则表达式和字符串方法

正则表达式和字符串方法 正则表达式 创建正则对象 构造函数字面量 匹配模式 i&#xff1a;忽略大小写m&#xff1a;多行匹配g&#xff1a;全局匹配 正则语法 正则作用/a/检查是否有a/a|b/检查是否有a或b{}量词&#xff0c;如{1,3}匹配1到3次&#xff0c;{m,}匹配m次以上…