Java7 Fork-Join 框架:任务切分,并行处理
概要
现代的计算机已经向多CPU方向发展,即使是普通的PC,甚至现在的智能手机、多核处理器已被广泛应用。在未来,处理器的核心数将会发展的越来越多。
虽然硬件上的多核CPU已经十分成熟,但是很多应用程序并未这种多核CPU做好准备,因此并不能很好地利用多核CPU的性能优势。
为了充分利用多CPU、多核CPU的性能优势,级软基软件系统应该可以充分“挖掘”每个CPU的计算能力,决不能让某个CPU处于“空闲”状态。为此,可以考虑把一个任务拆分成多个“小任务”,把多个"小任务"放到多个处理器核心上并行执行。当多个“小任务”执行完成之后,再将这些执行结果合并起来即可。
Java在JDK7之后加入了并行计算的框架Fork/Join,可以解决我们系统中大数据计算的性能问题。Fork/Join采用的是分治法,Fork是将一个大任务拆分成若干个子任务,子任务分别去计算,而Join是获取到子任务的计算结果,然后合并,这个是递归的过程。子任务被分配到不同的核上执行时,效率最高。伪代码如下:
- Result solve(Problem problem) {
- if (problem is small)
- directly solve problem
- else {
- split problem into independent parts
- fork new subtasks to solve each part
- join all subtasks
- compose result from subresults
- }
- }
Fork/Join框架的核心类是ForkJoinPool,它能够接收一个ForkJoinTask,并得到计算结果。ForkJoinTask有两个子类,RecursiveTask(有返回值)和RecursiveAction(无返回结果),我们自己定义任务时,只需选择这两个类继承即可
package test_lock; import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.RecursiveTask; public class SumTask extends RecursiveTask<Integer>{ private static final int THRESHOLD=20; private int[] array;
private int low;
private int high; public SumTask(int[] array_p,int low_p,int high_p){ this.array=array_p;
this.low=low_p;
this.high=high_p;
} @Override
protected Integer compute() {
// TODO Auto-generated method stub int sum =0; if((high-low + 1)<=THRESHOLD){ System.out.println(low +"-"+high +" 计算"); for(int i=low;i<=high;i++){
sum+=array[i];
}
}else{
System.out.println(low +"-"+high+" 切分"); //1. 一个大任务,分割成两个子任务; int mid=(low+high)/2;
SumTask left =new SumTask(array,low,mid);
SumTask right=new SumTask(array,mid+1,high);
//2.分别进行计算
invokeAll(left,right); //3.合并结果 sum =left.join()+right.join(); //另一种方法 try{
sum=left.get()+right.get();
}catch(Throwable e){
System.out.println(e.getMessage());
} }
return sum;
} public static void main(String[] args) {
// TODO Auto-generated method stub
// 1.6 泛型实例的创建可以通过类型推断来简化 可以去掉后面new部分的泛型类型,只用<>就可以了。
//使用泛型前
List strList = new ArrayList();
List<String> strList4 = new ArrayList<String>();
List<Map<String, List<String>>> strList5 = new ArrayList<Map<String, List<String>>>(); //编译器使用尖括号 (<>) 推断类型
List<String> strList0 = new ArrayList<String>();
List<Map<String, List<String>>> strList1 = new ArrayList<Map<String, List<String>>>();
List<String> strList2 = new ArrayList<>();
List<Map<String, List<String>>> strList3 = new ArrayList<>();
List<String> list = new ArrayList<>();
list.add("A");
// The following statement should fail since addAll expects
// Collection<? extends String>
//list.addAll(new ArrayList<>()); List<String> strList7 = new ArrayList<String>(); for(int i=0;i<10;i++){
strList7.add(String.valueOf(i));
} List<String> ll=new ArrayList<String>(); List<Map<String,List<String>>> ll1=new ArrayList<>(); strList7.forEach(o->{System.out.println(o);}); } }
package test_lock; import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool; public class fork_join { public static void main(String[] args) throws InterruptedException, ExecutionException {
// TODO Auto-generated method stub /**
* 下面以一个有返回值的大任务为例,介绍一下RecursiveTask的用法。
大任务是:计算随机的100个数字的和。
小任务是:每次只能20个数值的和。
*/ int[] array = genArray(); System.out.println(Arrays.toString(array)); int total=0;
for(int i=0;i<array.length;i++){
System.out.println("目标和是:"+total);
total+=array[i];
} System.out.println("目标和是:"+total); //1. 创建任务: SumTask sumTask=new SumTask(array,0,array.length-1); // 2。创建线程池,设置并行计算的个数 int processors=Runtime.getRuntime().availableProcessors();
System.out.println("processors="+processors);
ForkJoinPool forkJoinPool =new ForkJoinPool(processors*2); // 3.提交任务到线程池 forkJoinPool.submit(sumTask); long begin=System.currentTimeMillis();
//4 获取结果
Integer result =sumTask.get();//wait for long end =System.currentTimeMillis(); System.out.println(String.format("结果 %s,耗时 %sms",result,end-begin)); if(result==total){
System.out.println("测试成功!!");
}else{
System.out.println("fork join 调用失败!!!");
}
} private static int[] genArray() {
// TODO Auto-generated method stub int[] array=new int[100]; for(int i=0;i<100;i++){
array[i]=new Random().nextInt(500);
}
return array;
} }
结果为:
[412, 204, 449, 387, 245, 104, 73, 488, 42, 232, 84, 420, 101, 425, 3, 482, 8, 263, 492, 307, 312, 438, 29, 152, 467, 113, 265, 72, 429, 441, 199, 251, 416, 343, 386, 48, 403, 292, 232, 412, 469, 498, 139, 137, 181, 424, 52, 468, 260, 50, 164, 72, 259, 239, 448, 240, 415, 37, 186, 134, 147, 332, 172, 108, 205, 191, 194, 54, 359, 341, 348, 114, 405, 296, 14, 422, 275, 300, 413, 274, 279, 454, 213, 310, 96, 489, 96, 267, 250, 113, 252, 325, 163, 305, 206, 282, 145, 489, 253, 322]
目标和是:0....
目标和是:25744
目标和是:26066
processors=4
0-99 切分
0-49 切分
0-24 切分
50-99 切分
75-99 切分
25-49 切分
25-37 计算
13-24 计算
0-12 计算
38-49 计算
88-99 计算
50-74 切分
63-74 计算
50-62 计算
75-87 计算
结果 26066,耗时 2ms
测试成功!!
上面的代码是一个100个整数累加的任务,切分到小于20个数的时候直接进行累加,不再切分。
Java7 Fork-Join 框架:任务切分,并行处理的更多相关文章
- Java7任务并行执行神器:Fork&Join框架
Fork/Join是什么? Fork/Join框架是Java7提供的并行执行任务框架,思想是将大任务分解成小任务,然后小任务又可以继续分解,然后每个小任务分别计算出结果再合并起来,最后将汇总的结果作为 ...
- Java7任务并行执行神器:Fork&Join框架
原 Java7任务并行执行神器:Fork&Join框架 2018年01月12日 17:25:03 Java技术栈 阅读数:426 标签: JAVAFORKJOIN 更多 个人分类: Java ...
- 使用Java7提供Fork/Join框架
在Java7在.JDK它提供了多线程开发提供了一个非常强大的框架.这是Fork/Join框架.这是原来的Executors更多 进一步,在原来的基础上添加了并行分治计算中的一种Work-stealin ...
- 使用Java7提供的Fork/Join框架
http://blog.csdn.net/a352193394/article/details/39872923 使用Java7提供的Fork/Join框架 2014-10-07 23:55 4818 ...
- 聊聊并发(八)——Fork/Join框架介绍
作者 方腾飞 发布于 2013年12月23日 | 被首富的“一个亿”刷屏?不如定个小目标,先把握住QCon上海的优惠吧!2 讨论 分享到:微博微信FacebookTwitter有道云笔记邮件分享 ...
- 转:聊聊并发(八)——Fork/Join框架介绍
1. 什么是Fork/Join框架 Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架. 我们再通过 ...
- 多线程(五) Fork/Join框架介绍及实例讲解
什么是Fork/Join框架 Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架. 我们再通过For ...
- Fork/Join框架介绍
转http://www.infoq.com/cn/articles/fork-join-introduction/ 1. 什么是Fork/Join框架 Fork/Join框架是Java7提供了的一个用 ...
- 013-多线程-基础-Fork/Join框架、parallelStream讲解
一.概述 Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架. 它同ThreadPoolExecut ...
- ☕【Java技术指南】「并发编程专题」Fork/Join框架基本使用和原理探究(基础篇)
前提概述 Java 7开始引入了一种新的Fork/Join线程池,它可以执行一种特殊的任务:把一个大任务拆成多个小任务并行执行. 我们举个例子:如果要计算一个超大数组的和,最简单的做法是用一个循环在一 ...
随机推荐
- 【 C 】高级字符串查找之查找标记(token)函数 strtok介绍
我的csdn博客 一个字符串常常包含几个单独的部分,它们彼此被分隔开来.每次为了处理这些部分,你首先必须把它们从字符串中抽取出来. 这个任务有#include<string.h>中的str ...
- 【Hutool】Hutool工具类之日期时间工具——DateUtil
一.用于取代Date对象的DateTime对象 再也不用Date SimpleDateFormat Calendar之间倒腾来倒腾去了!日期创建-获取-操作一步到位! 如果JDK版本更新到了8及以上, ...
- 20155231 2016-2017-2《Java程序设计》课程总结
20155231 2016-2017-2<Java程序设计>课程总结 每周作业链接汇总 预备作业1:师生关系 预备作业2:优秀技能经验 预备作业3:虚拟机linux初接触 第一周作业:认识 ...
- 20155327 嵌入式C语言课堂补交
嵌入式C语言 题目要求 在作业本上完成附图作业,要认真看题目要求. 提交作业截图 作弊本学期成绩清零(有雷同的,不管是给别人传答案,还是找别人要答案都清零) 题目分析 分析一:提取插入时间 根据老师上 ...
- day 10 文件
1.文本文件 ,二进制文件 二进制文件:用vi 打开一个图片,MP3,视频 2.文件打开方式 # 重定向 文件不存在 文件存在 r error 文件开头 w 相当于 > 创建 覆盖,删除以前的内 ...
- Android:制作聊天气泡点9图
步骤一:选择res下的一张图片,右击选择“Create 9-Patch File” 步骤二:确定点9图的名字,只能修改.9.png之前的信息 步骤三:在同目录下会生成刚才创建的点9图,双击打开进行编辑 ...
- Karma与TSLint
TSLint TSLint是一个可扩展的静态分析工具,用于检查TypeScript代码的可读性,可维护性和功能性错误.收到现代编辑和构建系统的广泛支持,并且可以使用您自己的路由,配置和格式化. 安装 ...
- PHP:Iterator(迭代器)接口和生成器
迭代器 可在内部迭代自己的外部迭代器或类的接口.详情:http://php.net/manual/zh/class.iterator.php 接口摘要 Iterator extends Travers ...
- dbtool一bug跟踪记
注:这篇日志是好多年前,我还在从兴公司时写的.现在都从从兴公司离职很久了,从兴也没落了,可惜.看了一下,虽然出现了部分代码,但不至于泄漏什么机密,查bug过程的原理也有可以让新手借鉴的地方,就原文照搬 ...
- Delphi 实现照片抽奖-原创
有单位年会要用照片抽奖,上网搜了几个都不满意,且居然还要收费.自己写一个算了.只是有一点不爽,Delphi 7 在 Windows 7 64位下有问题,不能双击 dpr 文件直接打开项目! 关于性能: ...