ForkJoin是Java7提供的原生多线程并行处理框架,其基本思想是将大任务分割成小任务,最后将小任务聚合起来得到结果。fork是分解的意思, join是收集的意思. 它非常类似于HADOOP提供的MapReduce框架,只是MapReduce的任务可以针对集群内的所有计算节点,可以充分利用集群的能力完成计算任务。ForkJoin更加类似于单机版的MapReduce。

在fork/join框架中,若某个子问题由于等待另一个子问题的完成而无法继续执行。那么处理该子问题的线程会主动寻找其他尚未运行完成的子问题来执行。这种方式减少了线程的等待时间,提高了性能。子问题中应该避免使用synchronized关键词或其他方式方式的同步。也不应该是一阻塞IO或过多的访问共享变量。在理想情况下,每个子问题的实现中都应该只进行CPU相关的计算,并且只适用每个问题的内部对象。唯一的同步应该只发生在子问题和创建它的父问题之间。

Fork/Join使用两个类完成以上两件事情:

 
· ForkJoinTask: 我们要使用ForkJoin框架,必须首先创建一个ForkJoin任务。它提供在任务中执行fork()和join的操作机制,ForkJoinTask实现了Future接口,可以按照Future接口的方式来使用。在ForkJoinTask类中之重要的两个方法fork和join。fork方法用以一部方式启动任务的执行,join方法则等待任务完成并返回指向结果。在创建自己的任务是,最好不要直接继承自ForkJoinTask类,而要继承自ForkJoinTask类的子类RecurisiveTask或RecurisiveAction类
    . 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框架的使用的更多相关文章

  1. java fork-join框架应用和分析

    http://shmilyaw-hotmail-com.iteye.com/blog/1897636 java fork-join框架应用和分析 博客分类: concurrency multithre ...

  2. JAVA并行框架学习之ForkJoin

    当硬件处理能力不能按照摩尔定律垂直发展的时候,选择了水平发展,多核处理器已经广泛应用.未来随着技术的进一步发展,可能出现成百上千个处理核心,但现有的程序运行在多核心处理器上并不能得到较大性能的提升,主 ...

  3. Java并发编程原理与实战三十二:ForkJoin框架详解

    1.Fork/Join框架有什么用呢? ------->Fork使用来切分任务,Join是用来汇总结果.举个简单的栗子:任务是1+2+3+...+100这个任务(当然这个任务的结果有好的算法去做 ...

  4. Java并发包线程池之ForkJoinPool即ForkJoin框架(一)

    前言 这是Java并发包提供的最后一个线程池实现,也是最复杂的一个线程池.针对这一部分的代码太复杂,由于目前理解有限,只做简单介绍.通常大家说的Fork/Join框架其实就是指由ForkJoinPoo ...

  5. ForkJoin框架

    1. 什么是Fork/Join框架 Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架. 我们再通过 ...

  6. Java7 Fork-Join 框架:任务切分,并行处理

    概要 现代的计算机已经向多CPU方向发展,即使是普通的PC,甚至现在的智能手机.多核处理器已被广泛应用.在未来,处理器的核心数将会发展的越来越多.虽然硬件上的多核CPU已经十分成熟,但是很多应用程序并 ...

  7. JUC组件扩展(二)-JAVA并行框架Fork/Join(三):在任务中抛出异常

    在java当中,异常一共分为两种.一种是运行时异常,一种是非运行是异常. 非运行时异常:这些异常必须在方法上通过throws子句抛出.或者在方法体内进行try{…}catch{…}来捕获异常. 运行时 ...

  8. Java--8--新特性--串并行流与ForkJoin框架

    并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流.穿行流则相反,并行流的底层其实就是ForkJoin框架的一个实现. 那么先了解一下ForkJoin框架吧. Fork/Join ...

  9. Java集合框架List,Map,Set等全面介绍

    Java集合框架的基本接口/类层次结构: java.util.Collection [I]+--java.util.List [I]   +--java.util.ArrayList [C]   +- ...

  10. Java集合框架练习-计算表达式的值

    最近在看<算法>这本书,正好看到一个计算表达式的问题,于是就打算写一下,也正好熟悉一下Java集合框架的使用,大致测试了一下,没啥问题. import java.util.*; /* * ...

随机推荐

  1. DagScheduler 和 TaskScheduler

    DagScheduler 和 TaskScheduler 的任务交接 spark 调度器分为两个部分, 一个是 DagScheduler, 一个是 TaskScheduler, DagSchedule ...

  2. python的特性

    python使用c语言开发 1.面向对象的特性 面向对象的程序设计抽象出对象的行为和属性,把行为和属性分离开,但是又合理的组织在一起.它消除了保护类型.抽象类.接口等面向对象的元素,使得面向对象的概念 ...

  3. Golang Tcp粘包处理(转)

    在用golang开发人工客服系统的时候碰到了粘包问题,那么什么是粘包呢?例如我们和客户端约定数据交互格式是一个json格式的字符串: {"Id":1,"Name" ...

  4. Json/XML序列化和反序列化

    1.json序列化和反序列化 序列化是将对象状态转换为可保持或传输的格式的过程; 反序列化,它将流转换为对象; 1)Json.Net 推荐使用Json.Net类库,需要引入的命名空间; 序列化:Jso ...

  5. 知物由学 | 未来安全隐患:AI的软肋——故意欺骗神经网络

     本文由  网易云发布. “知物由学”是网易云易盾打造的一个品牌栏目,词语出自汉·王充<论衡·实知>.人,能力有高下之分,学习才知道事物的道理,而后才有智慧,不去求问就不会知道.“知物由学 ...

  6. ovs-vsctl 命令详解

    Open vSwitch中有多个命令,分别有不同的作用,大致如下: ovs-vsctl用于控制ovs db ovs-ofctl用于管理OpenFlow switch 的 flow ovs-dpctl用 ...

  7. win10 下Oracle安装

    在win10 64bit下安装oracle 11的时候,有些问题不注意,安装的时候才遇到就gg了.下面将介绍win10下安装oracle 11的步骤以及安装过程中遇到的一些问题及解决方案. 安装过程中 ...

  8. Python 断言 assert 的用法

    assert 后边接的表达式的返回值必须是布尔值 assert expression, "对错误的描述信息" 如果expression表达式返回的是True, 程序正常执行, 如果 ...

  9. python爬虫的页面数据解析和提取/xpath/bs4/jsonpath/正则(2)

    上半部分内容链接 : https://www.cnblogs.com/lowmanisbusy/p/9069330.html 四.json和jsonpath的使用 JSON(JavaScript Ob ...

  10. python 爬爬爬 基本函数~

    https://docs.python.org/2/howto/urllib2.html#data http://zhuoqiang.me/python-urllib2-usage.html #cod ...