Java 并发编程 Fork Join 一

来源:互联网 发布:java怎么创建数组 编辑:程序博客网 时间:2024/05/22 18:55

“分而治之”一直是一个非常有效地处理大量数据的方法。著名的MapReduce也是采取了分而治之的思想。 Fork就是分解任务,而Join 在Java线程中是等待意思 ,也就是等待计算结果。在实际应用中如果毫无顾忌地使用fork开启线程进行处理,那么很多可能会导致系统开启过多的线程而严重影响性能。所以在JDK中,给出了一个ForJoinPool线程池,对于fork方法并不急着开启线程,而是提交给ForkJoinPool线程池进行处理,以节省系统资源。

使用fork/Join 进行数据处理时的总体结构如图:

这里写图片描述

可以向ForkJoinPool线程池提交一个ForkJoinTask任务。所谓ForkJoinTask任务就是支持fork分解以及join等待的任务。ForkJoinTask有两个重要的子类 RecursiveAction和RecursiveTask。分别表示没有返回值的任务和可以携带返回值的任务。

public class CountTask extends RecursiveTask<Long> {    private static final int threshold = 1000;    private List<Integer> list;    public CountTask(List<Integer> list) {        this.list = list;    }    @Override    protected Long compute() {        long result = 0L;        int size = list.size();        System.out.println("size " + size);        if (size <= threshold) {            for (Integer i : list) {                result += i;            }        } else {            int count = size / threshold + 1;            List<CountTask> taskList = new ArrayList<CountTask>();            for (int i = 0; i < count; i++) {                int toindex = 0;                if (size < ((i + 1) * threshold)) {                    toindex = size;                } else {                    toindex = (i + 1) * threshold;                }                int fromIndex =i * threshold;                System.out.println("fromIndex  " + fromIndex +"<><>"+"toindex  " + toindex);                List<Integer> subList = list.subList(fromIndex, toindex);                CountTask c = new CountTask(subList);                taskList.add(c);                // c.fork();                c.fork();            }            for (CountTask c : taskList) {                result += c.join();            }        }        return result;    }    public static void main(String args[]) {        ForkJoinPool fp = new ForkJoinPool();        List<Integer> list = new ArrayList<Integer>();        for (int i = 0; i < 903000; i++) {            list.add(i);        }        CountTask task = new CountTask(list);        ForkJoinTask<Long> re = fp.submit(task);        try {            long res = re.get();            System.out.println(res);        } catch (InterruptedException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (ExecutionException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }}