Oracle官方教程之Fork/Join

简介:

原文链接译文链接,译者:Zach,校对:郑旭东

fork/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一节。 

目录
相关文章
|
1月前
|
SQL Oracle 关系型数据库
避坑,Oracle中left join 与 (+) 的区别
避坑,Oracle中left join 与 (+) 的区别
|
1月前
|
Oracle 关系型数据库 数据库
|
6月前
|
Oracle 关系型数据库 数据库
百度搜索:蓝易云【docker部署并配置oracle12c的cdb和pdb教程!】
以上是使用Docker部署和配置Oracle 12c CDB和PDB的简要教程。请注意,这只是一个概述,并且可能需要根据你的实际情况进行适当的调整和配置。建议参考Oracle官方文档和相关资源,以获得更详细和全面的指导。
104 2
|
8月前
|
SQL Oracle 关系型数据库
解决:Oracle数据库中Left join on 后面为null时匹配不上
解决:Oracle数据库中Left join on 后面为null时匹配不上
127 0
|
2月前
|
Oracle 关系型数据库 数据处理
某教程学习笔记(一):10、oracle数据库注入
某教程学习笔记(一):10、oracle数据库注入
17 0
|
3月前
|
SQL Oracle 关系型数据库
Oracle查询优化-left join、right join、inner join、full join和逗号的区别
【1月更文挑战第5天】【1月更文挑战第13篇】实际查询时,多表联查是常规操作,但是连接方式有多种。
74 0
|
4月前
|
Oracle 关系型数据库 数据库
windows Oracle Database 19c 卸载教程
打开任务管理器 ctrl+Shift+Esc可以快速打开任务管理器,找到oracle所有服务然后停止。 停止数据库服务 在开始卸载之前,确保数据库服务已经停止。你可以使用以下命令停止数据库服务: net stop OracleServiceORCL Universal Installer 卸载Oracle数据库程序 一般情况运行Oracle自带的卸载程序,如使用Universal Installer 工具卸载。 点击开始菜单找到Oracle,然后点击Oracle安装产品,再点击Universal Installer。 点击之后稍等一会然后会进入进入下图界面,点击卸载产品。 选中要删除的Orac
118 1
|
8月前
|
SQL Oracle 关系型数据库
Win11虚拟机安装Oracle 19c(保姆教程)
Oracle学习笔记 Oracle19c Windows11 instant client配置 远程连接 虚拟机
Win11虚拟机安装Oracle 19c(保姆教程)
|
8月前
|
Oracle 关系型数据库 数据库
一篇文章带你了解Oracle 数据库中 CROSS JOIN(cross join) 语法的作用
一篇文章带你了解Oracle 数据库中 CROSS JOIN(cross join) 语法的作用
311 0
|
9月前
|
Oracle 关系型数据库 数据库连接
Oracle 11g安装配置完美教程 - Windows(下)
Oracle 11g安装配置完美教程 - Windows(下)
154 0

推荐镜像

更多