Java并发工具包之印象篇四
转摘于http://www.importnew.com/26461.html
1、使用ForkJoinPool进行分叉和合并
ForkJoinPool在java7被引入。和ExecutorService很相似,除了一点不同。ForkJoinPool可以很方便地把任务分裂成几个更小的任务,这些分裂出来的任务也将会提交给ForkJoinPool。 任务可以继续分割成更小的子任务,只要它还能分割。
通过把自己分割成多个子任务,每个子任务可以由不同的CPU并行执行,或者被同一CPU上的不同线程执行。只有当给的任务过大,把它分割成几个子任务才有意义。把任务分割成子任务有一定开销,因此,对于小型任务,这个分割的消耗可能比每个子任务并发执行的消耗还要大。
ForkJoinPool是一个特殊的线程池,它的设计是为了更好的配合 分叉和合并任务分割的工作。
可以通过其构造方法创建一个ForkJoinPool。作为传递给ForkJoinPool构造方法的一个参数,可以定义你期望的并行级别。 并行级别表示你想要传递给ForkJoinPool的任务所需的线程或CPU数量。
ForkJoinPool forkJoin = new ForkJoinPool(4); //并行级别为4
可以提交两种类型的任务。一种是没有返回值的,另一种是有返回值的。 这两种类型分别由RecursiveAction和RecursiveTask表示。
1、RecursiveAction
它是一种没有任何返回值的任务。只是做一些工作,比如写数据到磁盘,然后就退出了。 一个RecursiveAction可以把自己的工作分割成更小的几块, 这样它们可以由独立的线程或者CPU执行。 我们可以通过继承来实现一个RecursiveAction。
import java.util.ArrayList; import java.util.List; import java.util.concurrent.RecursiveAction; public class MyRecursiveAction extends RecursiveAction { private long workLoad = 0; public MyRecursiveAction(long workLoad) { this.workLoad = workLoad; } @Override protected void compute() { //if work is above threshold, break tasks up into smaller tasks if(this.workLoad > 16) { System.out.println("Splitting workLoad : " + this.workLoad); List<MyRecursiveAction> subtasks = new ArrayList<MyRecursiveAction>(); subtasks.addAll(createSubtasks()); for(RecursiveAction subtask : subtasks){ subtask.fork(); } } else { System.out.println("Doing workLoad myself: " + this.workLoad); } } private List<MyRecursiveAction> createSubtasks() { List<MyRecursiveAction> subtasks = new ArrayList<MyRecursiveAction>(); MyRecursiveAction subtask1 = new MyRecursiveAction(this.workLoad / 2); MyRecursiveAction subtask2 = new MyRecursiveAction(this.workLoad / 2); subtasks.add(subtask1); subtasks.add(subtask2); return subtasks; } }
MyRecursiveAction myRecursiveAction =
new
MyRecursiveAction(
24
);
forkJoinPool.invoke(myRecursiveAction);
import java.util.ArrayList; import java.util.List; import java.util.concurrent.RecursiveTask; public class MyRecursiveTask extends RecursiveTask<Long> { private long workLoad = 0; public MyRecursiveTask(long workLoad) { this.workLoad = workLoad; } protected Long compute() { //if work is above threshold, break tasks up into smaller tasks if(this.workLoad > 16) { System.out.println("Splitting workLoad : " + this.workLoad); List<MyRecursiveTask> subtasks = new ArrayList<MyRecursiveTask>(); subtasks.addAll(createSubtasks()); for(MyRecursiveTask subtask : subtasks){ subtask.fork(); } long result = 0; for(MyRecursiveTask subtask : subtasks) { result += subtask.join(); } return result; } else { System.out.println("Doing workLoad myself: " + this.workLoad); return workLoad * 3; } } private List<MyRecursiveTask> createSubtasks() { List<MyRecursiveTask> subtasks = new ArrayList<MyRecursiveTask>(); MyRecursiveTask subtask1 = new MyRecursiveTask(this.workLoad / 2); MyRecursiveTask subtask2 = new MyRecursiveTask(this.workLoad / 2); subtasks.add(subtask1); subtasks.add(subtask2); return subtasks; } }
MyRecursiveTask myRecursiveTask =
new
MyRecursiveTask(
128
);
long
mergedResult = forkJoinPool.invoke(myRecursiveTask);
System.out.println(
"mergedResult = "
+ mergedResult);