Java线程(十一):Fork/Join-Java并行计算框架
并行计算在处处都有大数据的今天已经不是一个新奇的词汇了。如今已经有单机多核甚至多机集群并行计算。注意,这里说的是并行,而不是并发。严格的将,并行是指系统内有多个任务同一时候运行,而并发是指系统内有多个任务同一时候存在,不同的任务按时间分片的方式切换运行,因为切换的时间非常短。给人的感觉好像是在同一时候运行。
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(无返回结果),我们自定义任务时。仅仅需选择这两个类继承就可以。
类图例如以下:
以下来看一个实例:计算一个超大数组全部元素的和。代码例如以下:
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
/**
* @author: shuang.gao Date: 2015/7/14 Time: 8:16
*/
public class SumTask extends RecursiveTask<Integer> {
private static final long serialVersionUID = -6196480027075657316L;
private static final int THRESHOLD = 500000;
private long[] array;
private int low;
private int high;
public SumTask(long[] array, int low, int high) {
this.array = array;
this.low = low;
this.high = high;
}
@Override
protected Integer compute() {
int sum = 0;
if (high - low <= THRESHOLD) {
// 小于阈值则直接计算
for (int i = low; i < high; i++) {
sum += array[i];
}
} else {
// 1. 一个大任务切割成两个子任务
int mid = (low + high) >>> 1;
SumTask left = new SumTask(array, low, mid);
SumTask right = new SumTask(array, mid + 1, high);
// 2. 分别计算
left.fork();
right.fork();
// 3. 合并结果
sum = left.join() + right.join();
}
return sum;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
long[] array = genArray(1000000);
System.out.println(Arrays.toString(array));
// 1. 创建任务
SumTask sumTask = new SumTask(array, 0, array.length - 1);
long begin = System.currentTimeMillis();
// 2. 创建线程池
ForkJoinPool forkJoinPool = new ForkJoinPool();
// 3. 提交任务到线程池
forkJoinPool.submit(sumTask);
// 4. 获取结果
Integer result = sumTask.get();
long end = System.currentTimeMillis();
System.out.println(String.format("结果 %s 耗时 %sms", result, end - begin));
}
private static long[] genArray(int size) {
long[] array = new long[size];
for (int i = 0; i < size; i++) {
array[i] = new Random().nextLong();
}
return array;
}
}
我们通过调整阈值(THRESHOLD)。能够发现耗时是不一样的。实际应用中。假设须要切割的任务大小是固定的,能够经过測试,得到最佳阈值;假设大小不是固定的。就须要设计一个可伸缩的算法,来动态计算出阈值。
假设子任务非常多,效率并不一定会高。
未完待续。。
。
參考资料
http://gee.cs.oswego.edu/dl/papers/fj.pdf
https://docs.oracle.com/javase/tutorial/essential/concurrency/forkjoin.html
https://www.ibm.com/developerworks/cn/java/j-lo-forkjoin/
http://www.ibm.com/developerworks/cn/java/j-jtp11137.html
本文来自:高爽|Coder。原文地址:http://blog.csdn.net/ghsau/article/details/46287769,转载请注明。
Java线程(十一):Fork/Join-Java并行计算框架的更多相关文章
- Java 并发编程 -- Fork/Join 框架
概述 Fork/Join 框架是 Java7 提供的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架.下图是网上流传的 Fork Join 的 ...
- java 中的fork join框架
文章目录 ForkJoinPool ForkJoinWorkerThread ForkJoinTask 在ForkJoinPool中提交Task java 中的fork join框架 fork joi ...
- JAVA中的Fork/Join框架
看了下Java Tutorials中的fork/join章节,整理下. 什么是fork/join框架 fork/join框架是ExecutorService接口的一个实现,可以帮助开发人员充分利用多核 ...
- Java 并发之 Fork/Join 框架
什么是 Fork/Join 框架 Fork/Join 框架是一种在 JDk 7 引入的线程池,用于并行执行把一个大任务拆成多个小任务并行执行,最终汇总每个小任务结果得到大任务结果的特殊任务.通过其命名 ...
- Java并发编程--Fork/Join框架使用
上篇博客我们介绍了通过CyclicBarrier使线程同步,可是上述方法存在一个问题,那就是假设一个大任务跑了2个线程去完毕.假设线程2耗时比线程1多2倍.线程1完毕后必须等待线程2完毕.等待的过程线 ...
- 013-多线程-基础-Fork/Join框架、parallelStream讲解
一.概述 Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架. 它同ThreadPoolExecut ...
- Java对多线程~~~Fork/Join同步和异步帧
于Fork/Join骨架,当提交的任务,有两个同步和异步模式.它已被用于invokeAll()该方法是同步的.是任何 务提交后,这种方法不会返回直到全部的任务都处理完了.而还有还有一种方式,就是使用f ...
- 实现ThreadFactory接口生成自定义的线程给Fork/Join框架
Fork/Join框架是Java7中最有趣的特征之一.它是Executor和ExecutorService接口的一个实现,允许你执行Callable和Runnable任务而不用管理这些执行线程.这个执 ...
- 【fork/join】java并发编程-fork/join示例
package com.chinamobile.epic.tako.common.graphite.query.sync.impl; import com.google.common.collect. ...
随机推荐
- CListCtrl 之右键菜单
在使用CListCtrl时要为它添加一个右键菜单,步骤如下: 1. 响应CListCtrl的NM_RCLICK消息. 2. 添加一个菜单资源,在菜单资源中插入要添加到菜单内容. 一般存在两种方法: ...
- AI 经典书单 | 人工智能学习该读哪些书
转载 2018年01月16日 00:00:00 人工智能相关岗位中,涉及到的内容包含: 算法.深度学习.机器学习.自然语言处理.数据结构.Tensorflow.Python .数据挖掘.搜索开发. ...
- Jquery的分页插件
Jquery的分页插件, 用起来还不错. 来自: http://flaviusmatis.github.io/simplePagination.js/ 下载地址: https://github.c ...
- Android 从 Android 本地图库选择多个图片
原文地址 本文说明如何从 Android 本地图库选择多个图片.作者考虑很多解决方案. 演示从 Android 本地图库选择多个图片,有两个方法可以实现从图库中选择多个图片: 用 Intent 获取多 ...
- 获取屏幕的宽和高-Display中getHeight()和getWidth() 官方已废弃
getHeight()和getWidth() deprecated in API level 13 Display dp=getWindowManager().getDefaultDisplay(); ...
- ArcMap中条件语句的bug
ArcGIS作为一个十分强大的GIS工具平台,也有其bug,在以前在听说过关于SQL条件语句的bug,现在用的10.4.1,仍然与数据有关. 这个bug的出现也是非常偶然,与数据有密切的关系:发现省界 ...
- 牛客网-《剑指offer》-用两个栈实现队列
题目:http://www.nowcoder.com/practice/54275ddae22f475981afa2244dd448c6 C++ class Solution { public: vo ...
- 关于LINUX在中断(硬软)中不能睡眠的真正原因
摘自http://bbs.chinaunix.net/thread-2115820-1-1.html 4楼的回答 先把中断处理流程给出来 1.进入中断处理程序--->2.保存关键上下文----& ...
- hadoop mahout 算法和API说明
org.apache.mahout.cf.taste.hadoop.item.RecommenderJob.main(args) --input 偏好数据路径,文本文件.格式 userid\t ite ...
- HDU 3001 Travelling (三进制状态压缩 DP)
题意:有 n 个city,能够选择任一城市作为起点,每一个城市不能訪问超过2次, 城市之间有权值,问訪问所有n个城市须要的最小权值. 思路:由于每一个城市能够訪问最多两次,所以用三进制表示訪问的状态. ...