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);
 
 
2、RecursiveTask
它是一种会返回结果的任务。可以将自己的工作分割为若干更小任务,并将这些子任务的执行合并到一个集体结果。 可以有几个水平的分割和合并。
 
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);
 
 
 
posted @ 2018-05-15 16:51  秋水秋色  阅读(607)  评论(0编辑  收藏  举报