`
manzhizhen
  • 浏览: 289371 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Oracle官方教程之Fork/Join

 
阅读更多

ork/join框架是ExecutorService接口的一种具体实现,目的是为了帮助你更好地利用多处理器带来的好处。它是为那些能够被递归地拆解成子任务的工作类型量身设计的。其目的在于能够使用所有可用的运算能力来提升你的应用的性能。

类似于ExecutorService接口的其他实现,fork/join框架会将任务分发给线程池中的工作线程。fork/join框架的独特之处在与它使用工作窃取(work-stealing)算法。完成自己的工作而处于空闲的工作线程能够从其他仍然处于忙碌(busy)状态的工作线程处窃取等待执行的任务。
fork/join框架的核心是ForkJoinPool类,它是对AbstractExecutorService类的扩展。ForkJoinPool实现了工作偷取算法,并可以执行ForkJoinTask任务。

基本使用方法

使用fork/join框架的第一步是编写执行一部分工作的代码。你的代码结构看起来应该与下面所示的伪代码类似:

1 if (当前这个任务工作量足够小)
2     直接完成这个任务
3 else
4     将这个任务或这部分工作分解成两个部分
5     分别触发(invoke)这两个子任务的执行,并等待结果

你需要将这段代码包裹在一个ForkJoinTask的子类中。不过,通常情况下会使用一种更为具体的的类型,或者是RecursiveTask(会返回一个结果),或者是RecursiveAction
当你的ForkJoinTask子类准备好了,创建一个代表所有需要完成工作的对象,然后将其作为参数传递给一个ForkJoinPool实例的invoke()方法即可。

要清晰,先模糊

想要了解fork/join框架的基本工作原理,接下来的这个例子会有所帮助。假设你想要模糊一张图片。原始的source图片由一个整数的数组表示,每个整数表示一个像素点的颜色数值。与source图片相同,模糊之后的destination图片也由一个整数数组表示。
对图片的模糊操作是通过对source数组中的每一个像素点进行处理完成的。处理的过程是这样的:将每个像素点的色值取出,与周围像素的色值(红、黄、蓝三个组成部分)放在一起取平均值,得到的结果被放入destination数组。因为一张图片会由一个很大的数组来表示,这个流程会花费一段较长的时间。如果使用fork/join框架来实现这个模糊算法,你就能够借助多处理器系统的并行处理能力。下面是上述算法结合fork/join框架的一种简单实现:

01 public class ForkBlur extends RecursiveAction {
02 private int[] mSource;
03 private int mStart;
04 private int mLength;
05 private int[] mDestination;
06  
07 // Processing window size; should be odd.
08 private int mBlurWidth = 15;
09  
10 public ForkBlur(int[] src, int start, int length, int[] dst) {
11     mSource = src;
12     mStart = start;
13     mLength = length;
14     mDestination = dst;
15 }
16  
17 protected void computeDirectly() {
18     int sidePixels = (mBlurWidth - 1) / 2;
19     for (int index = mStart; index < mStart + mLength; index++) {
20         // Calculate average.
21         float rt = 0, gt = 0, bt = 0;
22         for (int mi = -sidePixels; mi <= sidePixels; mi++) {
23             int mindex = Math.min(Math.max(mi + index, 0),
24                                 mSource.length - 1);
25             int pixel = mSource[mindex];
26             rt += (float)((pixel & 0x00ff0000) >>16)
27                   / mBlurWidth;
28             gt += (float)((pixel & 0x0000ff00) >> 8)
29                   / mBlurWidth;
30             bt += (float)((pixel & 0x000000ff) >> 0)
31                   / mBlurWidth;
32         }
33  
34         // Reassemble destination pixel.
35         int dpixel = (0xff000000     ) |
36                (((int)rt) << 16) |
37                (((int)gt) <<  8) |
38                (((int)bt) <<  0);
39         mDestination[index] = dpixel;
40     }
41 }

接下来你需要实现父类中的compute()方法,它会直接执行模糊处理,或者将当前的工作拆分成两个更小的任务。数组的长度可以作为一个简单的阀值来判断任务是应该直接完成还是应该被拆分。

01 protected static int sThreshold = 100000;
02  
03 protected void compute() {
04     if (mLength < sThreshold) {
05         computeDirectly();
06         return;
07     }
08  
09     int split = mLength / 2;
10  
11     invokeAll(new ForkBlur(mSource, mStart, split, mDestination),
12               new ForkBlur(mSource, mStart + split, mLength - split,
13                            mDestination));
14 }

如果前面这个方法是在一个RecursiveAction的子类中,那么设置任务在ForkJoinPool中执行就再直观不过了。通常会包含以下一些步骤:

  1. 创建一个表示所有需要完成工作的任务。
    1 // source image pixels are in src
    2 // destination image pixels are in dst
    3 ForkBlur fb = new ForkBlur(src, 0, src.length, dst);
  2. 创建将要用来执行任务的ForkJoinPool
    1 ForkJoinPool pool = new ForkJoinPool();
  3. 执行任务。
    1 pool.invoke(fb);

想要浏览完成的源代码,请查看ForkBlur,其中还包含一些创建destination图片文件的额外代码。

标准实现

除了能够使用fork/join框架来实现能够在多处理系统中被并行执行的定制化算法(如前文中的ForkBlur.java例子),在Java SE中一些比较常用的功能点也已经使用fork/join框架来实现了。在Java SE 8中,java.util.Arrays类的一系列parallelSort()方法就使用了fork/join来实现。这些方法与sort()系列方法很类似,但是通过使用fork/join框架,借助了并发来完成相关工作。在多处理器系统中,对大数组的并行排序会比串行排序更快。这些方法究竟是如何运用fork/join框架并不在本教程的讨论范围内。想要了解更多的信息,请参见Java API文档。
其他采用了fork/join框架的方法还包括java.util.streams包中的一些方法,此包是作为Java SE 8发行版中Project Lambda的一部分。想要了解更多信息,请参见Lambda Expressions一节。

(全文完)如果您喜欢此文请点赞,分享,评论。


分享到:
评论

相关推荐

    Fork/Join例子

    Fork/Join例子

    fork/join 实例

    fork join 框架 生产使用实例,可以直接修改配置,实现业务。

    Fork/Join框架Package jsr166y

    Fork/Join框架Package jsr166y是Java 7并行编程类的的初步版本(Preliminary versions of classes targeted for Java 7.)

    java NIO用法及java fork/join 用法源码工程

    1.ServerSocketChannel与SocketChannel通讯 2.java Fork/Join 与ThreadPool使用

    Java中的Fork/Join框架

     fork/join框架与其它ExecutorService的实现类相似,会给线程池中的线程分发任务,不同之处在于它使用了工作窃取算法,所谓工作窃取,指的是对那些处理完自身任务的线程,会从其它线程窃取任务执行。  fork/join...

    JDK7中的ForkJoin模式

    而 JDK 7 中将会加入的 Fork/Join 模式是处理并行编程的一个经典的方法。虽然不能解决所有的问题,但是在它的适用范围之内,能够轻松的利用多个 CPU 提供的计算资源来协作完成一个复杂的计算任务。通过利用 Fork/...

    java Fork Join框架及使用

    java Fork Join框架及使用,java自带的多线程框架,来处理多线程的问题

    Java Fork/Join框架

    Fork/Join框架是Java7中新增的一项特性,也是Java7平台的其中一项主要改进。下面我们就来简单探讨下Java的Fork/Join框架

    java fork-join框架介绍

    fork/join框架是ExecutorService接口的一个实现,可以帮助开发人员充分利用多核处理器的优势,编写出并行执行的程序,提高应用程序的性能;设计的目的是为了处理那些可以被递归拆分的任务。

    Fork:join框架与CompleteableFuture源码解析.pptx

    全网第一篇通过图文介绍Fork/Join框架与CompleteableFuture的PPT

    浅谈Java Fork/Join并行框架

    主要介绍了浅谈Java Fork/Join并行框架,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    ForkJoinUtil.java,一个分而治之的框架工具类

    Fork/Join框架的测试demo,含源代码。 Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。 我们再通过Fork和Join这两个...

    Java通过Fork/Join优化并行计算

    主要为大家详细介绍了Java通过Fork、Join来优化并行计算,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

    Fork-Join框架演示

    Java Fork-Join 论文 排序

    Java并发Fork and join

    Java并发网文归并总结。Fork and join,比较详细

    译文:Fork and Join: Java Can Excel at Painless Parallel Programming Too!

    译文:Fork and Join: Java Can Excel at Painless Parallel Programming Too!(Fork and Join Java也可以轻松地编写并发程序)

    Fork Join框架机制详解.docx

    Java提供Fork/Join框架用于并行执行任务,核心的思想就是将一个大任务切分成多个小任务,然后汇总每个小任务的执行结果得到这个大任务的最终结果。 这种机制策略在分布式数据库中非常常见,数据分布在不同的数据库的...

    eclipse-collections-forkjoin-7.1.2-API文档-中文版.zip

    赠送jar包:eclipse-collections-forkjoin-7.1.2.jar; 赠送原API文档:eclipse-collections-forkjoin-7.1.2-javadoc.jar; 赠送源代码:eclipse-collections-forkjoin-7.1.2-sources.jar; 赠送Maven依赖信息文件:...

    ForkJoin并发框架入门示例

    介绍了ForkJoin并发框架,供有java基础者学习,工作配合使用,附件带有PPT,介绍并发与并行区别,和ForkJoin代码范例,资源来自网络,分享分享!

Global site tag (gtag.js) - Google Analytics