java-forkjoin框架的使用
ForkJoin是Java7提供的原生多线程并行处理框架,其基本思想是将大任务分割成小任务,最后将小任务聚合起来得到结果。fork是分解的意思, join是收集的意思. 它非常类似于HADOOP提供的MapReduce框架,只是MapReduce的任务可以针对集群内的所有计算节点,可以充分利用集群的能力完成计算任务。ForkJoin更加类似于单机版的MapReduce。
在fork/join框架中,若某个子问题由于等待另一个子问题的完成而无法继续执行。那么处理该子问题的线程会主动寻找其他尚未运行完成的子问题来执行。这种方式减少了线程的等待时间,提高了性能。子问题中应该避免使用synchronized关键词或其他方式方式的同步。也不应该是一阻塞IO或过多的访问共享变量。在理想情况下,每个子问题的实现中都应该只进行CPU相关的计算,并且只适用每个问题的内部对象。唯一的同步应该只发生在子问题和创建它的父问题之间。
Fork/Join使用两个类完成以上两件事情:
. RecursiveAction,用于没有返回结果的任务
. RecursiveTask,用于有返回值的任务
源码推荐查询 jdk8的
· ForkJoinPool:task要通过ForkJoinPool来执行,分割的子任务也会添加到当前工作线程的双端队列中,进入队列的头部。当一个工作线程中没有任务时,会从其他工作线程的队列尾部获取一个任务。
2个构造方法
ForkJoinPool(int parallelism) 创建一个包含parallelism个并行线程的ForkJoinPool。 ForkJoinPool() 以Runtime.availableProcessors()方法的返回值作为parallelism参数来创建ForkJoinPool。
3种方式启动
异步执行 execute(ForkJoinTask) ForkJoinTask.fork
等待获取结果 invoke(ForkJoinTask) ForkJoinTask.invoke
执行,获取Future submit(ForkJoinTask) ForkJoinTask.fork(ForkJoinTask are Futures)
异常处理:
ForkJoinTask在执行的时候可能会抛出异常,但是没办法在主线程里直接捕获异常,所以ForkJoinTask提供了isCompletedAbnormally()方法来检查任务是否已经抛出异常或已经被取消了,并且可以通过ForkJoinTask的getException方法获取异常.
getException方法返回Throwable对象,如果任务被取消了则返回CancellationException。如果任务没有完成或者没有抛出异常则返回null。
if(task.isCompletedAbnormally()) {
System.out.println(task.getException());
}
然后, 代码展示
import java.util.concurrent.ForkJoinPool
import java.util.concurrent.ForkJoinTask
import java.util.concurrent.RecursiveTask
/**
* fork
* 对一个大数组进行并行求和的RecursiveTask
*
* 大任务可以拆成小任务,小任务还可以继续拆成更小的任务,最后把任务的结果汇总合并,得到最终结果,这种模型就是Fork/Join模型。
Java7引入了Fork/Join框架,我们通过RecursiveTask这个类就可以方便地实现Fork/Join模式。
* Created by wenbronk on 2017/7/13.
*/
class ForkJoinTest extends RecursiveTask<Long> { static final int THRESHOLD =
long[] array
int start
int end ForkJoinTest(long[] array, int start, int end) {
this.start = start
this.end = end
this.array = array
}
@Override
protected Long compute() { if (end - start < THRESHOLD) {
long sum =
for (int i = start; i < end; i++) {
sum += array[i]
}
try {
Thread.sleep()
} catch (Exception e) {
e.printStackTrace()
}
println String.format('compute %d %d = %d', start, end, sum)
} // 对于大任务, 分多线程执行
int middle = (end + start) /
println String.format('split %d %d => %d %d, %d %d', start, end, start, middle, middle, end) def subtask1 = new ForkJoinTest(this.array, start, middle);
def subtask2 = new ForkJoinTest(this.array, middle, end);
invokeAll(subtask1, subtask2) Long subresult1 = subtask1.join()
Long subresult2 = subtask2.join() Long result = subresult1 + subresult2 System.out.println("result = " + subresult1 + " + " + subresult2 + " ==> " + result);
return result
} public static void main(String[] args) throws Exception {
// 创建随机数组成的数组:
long[] array = new long[];
// fillRandom(array);
// fork/join task:
ForkJoinPool fjp = new ForkJoinPool(); // 最大并发数4
ForkJoinTask<Long> task = new ForkJoinTest(array, , array.length);
long startTime = System.currentTimeMillis();
Long result = fjp.invoke(task);
long endTime = System.currentTimeMillis();
System.out.println("Fork/join sum: " + result + " in " + (endTime - startTime) + " ms.");
}
}
java代码的实现
package com.wenbronk.test; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask; /**
* forkjoin的简单易用
* Created by wenbronk on 2017/7/26.
*/
public class CountTask extends RecursiveTask<Integer>{
private volatile static int count = ;
private int start;
private int end; public CountTask(int start, int end) {
this.start = start;
this.end = end;
} public static final int threadhold = ; @Override
protected Integer compute() {
int sum = ;
System.out.println("开启了一条线程单独干: " + count++);
// 如果任务足够小, 就直接执行
boolean canCompute = (end - start) <= threadhold;
if (canCompute) {
for (int i = start; i <= end; i++) {
sum += i;
}
}else {
//任务大于阈值, 分裂为2个任务
int middle = (start + end) / ;
CountTask countTask1 = new CountTask(start, middle);
CountTask countTask2 = new CountTask(middle + , end); // 开启线程
// countTask1.fork();
// countTask2.fork();
invokeAll(countTask1, countTask2); Integer join1 = countTask1.join();
Integer join2 = countTask2.join(); // 结果合并
sum = join1 + join2;
}
return sum;
} // 测试
public static void main(String[] args) throws ExecutionException, InterruptedException {
ForkJoinPool forkJoinPool = new ForkJoinPool(); CountTask countTask = new CountTask(, );
ForkJoinTask<Integer> result = forkJoinPool.submit(countTask);
System.out.println(result.get());
}
}
java-forkjoin框架的使用的更多相关文章
- java fork-join框架应用和分析
http://shmilyaw-hotmail-com.iteye.com/blog/1897636 java fork-join框架应用和分析 博客分类: concurrency multithre ...
- JAVA并行框架学习之ForkJoin
当硬件处理能力不能按照摩尔定律垂直发展的时候,选择了水平发展,多核处理器已经广泛应用.未来随着技术的进一步发展,可能出现成百上千个处理核心,但现有的程序运行在多核心处理器上并不能得到较大性能的提升,主 ...
- Java并发编程原理与实战三十二:ForkJoin框架详解
1.Fork/Join框架有什么用呢? ------->Fork使用来切分任务,Join是用来汇总结果.举个简单的栗子:任务是1+2+3+...+100这个任务(当然这个任务的结果有好的算法去做 ...
- Java并发包线程池之ForkJoinPool即ForkJoin框架(一)
前言 这是Java并发包提供的最后一个线程池实现,也是最复杂的一个线程池.针对这一部分的代码太复杂,由于目前理解有限,只做简单介绍.通常大家说的Fork/Join框架其实就是指由ForkJoinPoo ...
- ForkJoin框架
1. 什么是Fork/Join框架 Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架. 我们再通过 ...
- Java7 Fork-Join 框架:任务切分,并行处理
概要 现代的计算机已经向多CPU方向发展,即使是普通的PC,甚至现在的智能手机.多核处理器已被广泛应用.在未来,处理器的核心数将会发展的越来越多.虽然硬件上的多核CPU已经十分成熟,但是很多应用程序并 ...
- JUC组件扩展(二)-JAVA并行框架Fork/Join(三):在任务中抛出异常
在java当中,异常一共分为两种.一种是运行时异常,一种是非运行是异常. 非运行时异常:这些异常必须在方法上通过throws子句抛出.或者在方法体内进行try{…}catch{…}来捕获异常. 运行时 ...
- Java--8--新特性--串并行流与ForkJoin框架
并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流.穿行流则相反,并行流的底层其实就是ForkJoin框架的一个实现. 那么先了解一下ForkJoin框架吧. Fork/Join ...
- Java集合框架List,Map,Set等全面介绍
Java集合框架的基本接口/类层次结构: java.util.Collection [I]+--java.util.List [I] +--java.util.ArrayList [C] +- ...
- Java集合框架练习-计算表达式的值
最近在看<算法>这本书,正好看到一个计算表达式的问题,于是就打算写一下,也正好熟悉一下Java集合框架的使用,大致测试了一下,没啥问题. import java.util.*; /* * ...
随机推荐
- Codeforces805D. Minimum number of steps 2017-05-05 08:46 240人阅读 评论(0) 收藏
D. Minimum number of steps time limit per test 1 second memory limit per test 256 megabytes input st ...
- Firemonkey里触发home按键被按下的事件
吾八哥我最近在使用Delphi里的Firemonkey平台写一个叫“由由密码管家”的APP工具,是跨多平台的,如ios/android/windows/macOs.由于是用于密码管理的,那么在手机里操 ...
- WindowsPhone 8.1 语音命令资料
快速入门:语音命令(XAML) http://msdn.microsoft.com/library/windows/apps/xaml/dn630430.aspx/ 语音命令元素和属性参考(XAML) ...
- SQL Server Extended Events 进阶 3:使用Extended Events UI
开始采用Extended Events 最大的阻碍之一是需要使用Xquery和XML知识用来分析数据.创建和运行会话可以用T-SQL完成,但是无论使用什么目标,数据都会被转换为XML.这个限制在SQL ...
- Facebook支撑万亿Post搜索背后的技术窥探
转自http://www.csdn.net/article/2013-10-29/2817333-under-the-hood-building-posts-search 近日,Facebook为po ...
- ASP.NET MVC 中单独的JS文件中获取Controller中设定的值
1,在Controller中的Action 中将指定值写上. // // GET: /Home/ public ActionResult Index() ...
- 阿里云ECS服务器windows环境下配置redis
一.下载解压redis github下载地址:https://github.com/MSOpenTech/redis/tags 下载的是Redis-x64-3.2.100版本,Redis-x64-3. ...
- Android Studio - No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android
错误提示: No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android 错 ...
- jvm高级特性(6)(线程的种类,调度,状态,安全程度,实现安全的方法,同步种类,锁优化,锁种类)
JVM高级特性与实践(十三):线程实现 与 Java线程调度 JVM高级特性与实践(十四):线程安全 与 锁优化 一. 线程的实现 线程其实是比进程更轻量级的调度执行单位. 线程的引入,可以把一个检查 ...
- java中的IO流(输入流与输出流)概述与总结
Java中IO流,输入输出流概述与总结 总结的很粗糙,以后时间富裕了好好修改一下. 1:Java语言定义了许多类专门负责各种方式的输入或者输出,这些类都被放在java.io包中.其中, 所有输入流类都 ...