Fork me on GitHub

Fork/Jion框架详解


Fork/Jion框架可以干什么

如果你要处理1万条数据,但是你的能力暂时还不够,一个简单快捷的办法就是你可以把每次只处理100条,等到处理100次之后再把所有的结果聚合起来你就处理完了这1万条数据。

Fork/Join就是是Java7提供的原生多线程并行处理框架,它的基本思想就是将大任务分割成小任务,最后将小任务聚合起来得到结果。


如何使用Fork/Jion框架

我们要使用ForkJoin框架,首先要创建一个ForkJoin任务。它提供在任务中执行fork()和join的操作机制。
fork用来创建子线程,可以让程序多一个执行分枝,jion在我们之前文章中已经提到了,那就是等待结果。
通常我们可以按需继承如下两个类来使用Fork/Jion框架:

  1. RecursiveAction,用于没有返回结果的任务

  2. RecursiveTask,用于有返回值的任务


代码示例

下方是一个使用Fork/Jion框架计算1到10000的所有数值的和的一个简单的代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
public class ForkJionDemo extends RecursiveTask<Integer> {
//任务拆分阈值
public static final int threshold = 100;
//计算起始值
private int start;
//计算结束值
private int end;

public ForkJionDemo(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 {
List<ForkJionDemo> forkJionDemoList=new ArrayList<>();
//将任务拆分成100份
for(int i=0;i<100;i++){
//计算这个一份任务要计算的起点和终点,如果终点大于最大值则使用最大值为终点
int last=(start+threshold)>end?end:(start+threshold);
ForkJionDemo forkJionDemo = new ForkJionDemo(start, last);
//下一份任务的起点要更新
start+=threshold+1;
forkJionDemoList.add(forkJionDemo);
//提交子任务
forkJionDemo.fork();
}
//汇总拆分完毕后的任务结果
for(ForkJionDemo forkJionDemo:forkJionDemoList){
sum += forkJionDemo.join();
}
}
return sum;
}

public static void main(String[] args) {
//构造一个任务线程池
ForkJoinPool forkjoinPool = new ForkJoinPool();
//创建一个计算1到10000之间所有数的和的任务
ForkJionDemo forkJionDemo = new ForkJionDemo(1, 10000);
//将任务提交到任务线程池
Future<Integer> result = forkjoinPool.submit(forkJionDemo);
try {
//打印最后计算结果
System.out.println(result.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}


使用Fork/Jion框架需要注意的点

如果使用Fork/Jion框架计算的任务量特别庞大时很可能会出现以下2种情况:
fork的线程越来越多导致性能严重下降
函数调用层次越来越深导致栈溢出

本文所有源码参见:https://github.com/shiyujun/syj-study-demo

 

博客所有文章首发于公众号《Java学习录》转载请保留
扫码关注公众号即可领取2000GJava学习资源

 


Fork/Jion框架可以干什么

如果你要处理1万条数据,但是你的能力暂时还不够,一个简单快捷的办法就是你可以把每次只处理100条,等到处理100次之后再把所有的结果聚合起来你就处理完了这1万条数据。

Fork/Join就是是Java7提供的原生多线程并行处理框架,它的基本思想就是将大任务分割成小任务,最后将小任务聚合起来得到结果。


如何使用Fork/Jion框架

我们要使用ForkJoin框架,首先要创建一个ForkJoin任务。它提供在任务中执行fork()和join的操作机制。
fork用来创建子线程,可以让程序多一个执行分枝,jion在我们之前文章中已经提到了,那就是等待结果。
通常我们可以按需继承如下两个类来使用Fork/Jion框架:

  1. RecursiveAction,用于没有返回结果的任务

  2. RecursiveTask,用于有返回值的任务


代码示例

下方是一个使用Fork/Jion框架计算1到10000的所有数值的和的一个简单的代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
public class ForkJionDemo extends RecursiveTask<Integer> {
//任务拆分阈值
public static final int threshold = 100;
//计算起始值
private int start;
//计算结束值
private int end;

public ForkJionDemo(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 {
List<ForkJionDemo> forkJionDemoList=new ArrayList<>();
//将任务拆分成100份
for(int i=0;i<100;i++){
//计算这个一份任务要计算的起点和终点,如果终点大于最大值则使用最大值为终点
int last=(start+threshold)>end?end:(start+threshold);
ForkJionDemo forkJionDemo = new ForkJionDemo(start, last);
//下一份任务的起点要更新
start+=threshold+1;
forkJionDemoList.add(forkJionDemo);
//提交子任务
forkJionDemo.fork();
}
//汇总拆分完毕后的任务结果
for(ForkJionDemo forkJionDemo:forkJionDemoList){
sum += forkJionDemo.join();
}
}
return sum;
}

public static void main(String[] args) {
//构造一个任务线程池
ForkJoinPool forkjoinPool = new ForkJoinPool();
//创建一个计算1到10000之间所有数的和的任务
ForkJionDemo forkJionDemo = new ForkJionDemo(1, 10000);
//将任务提交到任务线程池
Future<Integer> result = forkjoinPool.submit(forkJionDemo);
try {
//打印最后计算结果
System.out.println(result.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}


使用Fork/Jion框架需要注意的点

如果使用Fork/Jion框架计算的任务量特别庞大时很可能会出现以下2种情况:
fork的线程越来越多导致性能严重下降
函数调用层次越来越深导致栈溢出

本文所有源码参见:https://github.com/shiyujun/syj-study-demo

 

 

 


posted @ 2019-03-31 22:39  石玉军  阅读(267)  评论(0编辑  收藏  举报