当硬件处理能力不能按照摩尔定律垂直发展的时候,选择了水平发展,多核处理器已经广泛应用。未来随着技术的进一步发展,可能出现成百上千个处理核心,但现有的程序运行在多核心处理器上并不能得到较大性能的提升,主要的瓶颈在于程序本身的并发处理能力不强,不能够合理的利用多核心资源。
 
现有的处理方案是从软件入手,试图采用多线程,是程序在同一时间支持多个任务的计算,这种多线程的处理方案在处理器数目较少的情况下可以较为明显的提高应用性能,但我们更加青睐于由硬件实现的多线程处理模式,但这一领域至今没有很好的结果。
 

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

 
即使不通过mapreduce,仅有应用程序本身进行任务的分解与合成也是可以的,但从实现难度上考虑,自己实现可能会带来较大规模的复杂度,因此程序员急需一种范式来处理这一类的任务。在处理多线程中已经有了如AKKA这样的基于ACTOR模型的框架,而FORKJOIN则是针对具有明显可以进行任务分割特性需求的实现。
 
其场景为:如果一个应用程序能够被分解成多个子任务,而且结合多个子任务的结果就能够得到最终的答案,那么它就适合使用FORK/JOIN模式来实现。
 
 
Fork/Join使用两个类完成以上两件事情:
 
· ForkJoinTask: 我们要使用ForkJoin框架,必须首先创建一个ForkJoin任务。它提供在任务中执行fork()和join的操作机制,通常我们不直接继承ForkjoinTask类,只需要直接继承其子类。
 
    1. RecursiveAction,用于没有返回结果的任务
 
    2. RecursiveTask,用于有返回值的任务
 
· ForkJoinPool:task要通过ForkJoinPool来执行,分割的子任务也会添加到当前工作线程的双端队列中,进入队列的头部。当一个工作线程中没有任务时,会从其他工作线程的队列尾部获取一个任务。
 
ForkJoin框架使用了工作窃取的思想(work-stealing),算法从其他队列中窃取任务来执行,其工作流图为:
 
 
通过此算法降低线程等待和竞争。
 
下面是示例:
 
package com.inspur.jiyq.forkjoin.sum;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.Future;
import java.util.concurrent.RecursiveTask; public class CountTask extends RecursiveTask<Integer>
{
private static final long serialVersionUID = -3611254198265061729L; public static final int threshold = 2;
private int start;
private int end; public CountTask(int start, int end)
{
this.start = start;
this.end = end;
} @Override
protected Integer compute()
{
int sum = 0; //如果任务足够小就计算任务
boolean canCompute = (end - start) <= threshold;
if(canCompute)
{
for (int i=start; i<=end; i++)
{
sum += i;
}
}
else
{
// 如果任务大于阈值,就分裂成两个子任务计算
int middle = (start + end)/2;
CountTask leftTask = new CountTask(start, middle);
CountTask rightTask = new CountTask(middle+1, end); // 执行子任务
leftTask.fork();
rightTask.fork(); //等待任务执行结束合并其结果
int leftResult = leftTask.join();
int rightResult = rightTask.join(); //合并子任务
sum = leftResult + rightResult; } return sum;
} public static void main(String[] args)
{
ForkJoinPool forkjoinPool = new ForkJoinPool(); //生成一个计算任务,计算1+2+3+4
CountTask task = new CountTask(1, 100); //执行一个任务
Future<Integer> result = forkjoinPool.submit(task); try
{
System.out.println(result.get());
}
catch(Exception e)
{
System.out.println(e);
}
} }
 
像这种求和以及排序的需求都可以通过FORKJOIN思想来实现,但在实际使用时还是要进行必要的性能测试来确认性能提升的幅度。
 
在上面这段代码中,定义了一个累加的任务,在compute方法中,判断当前值是否小于一个阈值,如果是则计算,如果不是则继续拆分,并合并子任务的中间结果。
 
任务定义后执行任务,Fork/Join提供一个和Executor框架的扩展线程来执行任务。
 
参考:
 
 

JAVA并行框架学习之ForkJoin的更多相关文章

  1. Java集合框架学习(一)List

    先附一张Java集合框架图. 从上面的集合框架图可以看到,Java集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射.Coll ...

  2. Java集合框架学习

    集合框架 集合框架的目标 该框架必须是高性能的.基本集合(动态数组,链表,树,哈希表)的实现必须是高效的. 该框架允许 不同类型的集合,以类似的方式工作,具有高度的互操作性. 对一个集合的扩展和适应必 ...

  3. JAVA并行框架:Fork/Join

    一.背景 虽然目前处理器核心数已经发展到很大数目,但是按任务并发处理并不能完全充分的利用处理器资源,因为一般的应用程序没有那么多的并发处理任务.基于这种现状,考虑把一个任务拆分成多个单元,每个单元分别 ...

  4. JUC组件扩展(二)-JAVA并行框架Fork/Join(一):简介和代码示例

    一.背景 虽然目前处理器核心数已经发展到很大数目,但是按任务并发处理并不能完全充分的利用处理器资源,因为一般的应用程序没有那么多的并发处理任务.基于这种现状,考虑把一个任务拆分成多个单元,每个单元分别 ...

  5. Java SSH框架学习(入门)

    SSH就是 struts+spring+hibernate 的一个集成框架,是java中一种流行的JAVA WEB 应用程序开源框架.由于我最熟悉的还是ASP.NET的的MVC和Python的Djan ...

  6. JUC组件扩展(二)-JAVA并行框架Fork/Join(四):监控Fork/Join池

    Fork/Join 框架是为了解决可以使用 divide 和 conquer 技术,使用 fork() 和 join() 操作把任务分成小块的问题而设计的.主要实现这个行为的是 ForkJoinPoo ...

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

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

  8. java三大框架学习总结(1)

    企业里并不一定就会用这三种框架,关键是要你能懂得面向对象的原理,以及对服务器客户端请求响应方式的理解,再加上你对缓存的利用,这才能成为真正的高手,框架就好比是一把武器,它最多是能帮你更好的杀敌,而如果 ...

  9. Java Executor 框架学习总结

    大多数并发都是通过任务执行的方式来实现的.一般有两种方式执行任务:串行和并行. class SingleThreadWebServer { public static void main(String ...

随机推荐

  1. Linux下面对于VIM编辑器的代码折叠使用与screen

    VIM设置代码折叠 1. 折叠方式 可用选项 'foldmethod' 来设定折叠方式:set fdm=*****.有 6 种方法来选定折叠:          manual           手工 ...

  2. [译]Java Thread join示例与详解

    Java Thread join示例与详解 Java Thread join方法用来暂停当前线程直到join操作上的线程结束.java中有三个重载的join方法: public final void ...

  3. Openvpn完美解决公司网络没有固定公网IP的问题

    方案背景: 公司办公网络使用长城宽带上网有一段时间了,有4个固定IP(2个电信,2个网通),链路不太稳定,经常有问题,因此考虑取消长城宽带,采用原来的adsl上网.但是有个问题,因为公司内网有几台服务 ...

  4. 开博第一篇:DHT 爬虫的学习记录

    经过一段时间的研究和学习,大致了解了DHT网络的一些信息,大部分还是参会别人的相关代码,一方面主要对DHT爬虫原理感兴趣,最主要的是为了学习python,大部分是别人的东西原理还是引用别人的吧 DHT ...

  5. Device disconnected

    问题:android 调试的时候,Logcat没有任何输出,提示Device  disconnected 解决:Devices -- Reset adb

  6. mac 下 配置 xhprof

    1: 下载 安装 xhprof wget http://pecl.php.net/get/xhprof-0.9.3.tgztar zxf xhprof-0.9.3.tgzcd xhprof-0.9.3 ...

  7. 第1章 Git的版本控制之道

    版本控制系统(Version Control System,VCS)可以帮助我们记录和跟踪项目中各文件内容的修改变化. 1.1 版本库 版本库(Repository)是版本控制系统用来存储所有历史数据 ...

  8. cocos2dx之C++调用Lua

    原文地址:http://blog.csdn.net/dingkun520wy/article/details/49839701 1.引入头文件 #include "cocos2d.h&quo ...

  9. ITaCS Change Password web part

    http://changepassword.codeplex.com/ A webpart is used to change your sharepoint AD password.

  10. Any Way You Slice It (向量旋转 以及 判断线段是否相交)(模板)

    http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=11353 #include<iostream> # ...