【Java并发编程】Fork/Join

什么是Fork/Join

Java提供了ForkJoinPool线程池,你可以向该线程池里提交一个ForkJoinTask任务。而这个ForkJoinTask就支持Fork(分解)和Join(等待)的功能。简而言之就是采用分治法,将一个任务分解为多个子任务,最后将多个子任务计算的结果归并,像不像Hadoop里的Mapreduce。

如何使用Fork/Join

  1. 首先创建ForkJoinPool线程池:
 ForkJoinPool pool = new ForkJoinPool();
  1. 接着创建一个ForkJoinPool,通过ForkJoinTask接口下的submit函数提交任务。‘
    public <T> ForkJoinTask<T> submit(ForkJoinTask<T> task) {

ForkJoinTask拥有两个子类:RecursiveTask和RecursiveAction。其中RecursiveTask是能够返回值的,而RecursiveAction是无返回值的。

  1. 创建一个任务类,通过继承RecursiveTask或RecursiveAction。
  2. 重写compute方法,compute内的主要功能是完成计算任务、对任务进行拆分。

代码示例

import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;

public class Main extends RecursiveTask<Long> {
    private static final int THRESHOLD = 10000;
    private long start;
    private long end;

    public Main(long start, long end) {
        this.start = start;
        this.end = end;
    }

    public static void main(String[] args) {
        ForkJoinPool pool = new ForkJoinPool();
        Main task = new Main( 0, 200000L );
        ForkJoinTask<Long> res = pool.submit( task );
        try {
            long r = res.get();
            System.out.println( r );
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected Long compute() {
        long sum = 0;
        //计算范围是否小于限定范围
        boolean canCompute = (end - start) < THRESHOLD;
        //小于直接求和
        if (canCompute) {
            for (long i = start; i <= end; i++) {
                sum += i;
            }
        }
        //大于等于时
        else {
            long step = (start + end) / 100;
            ArrayList<Main> subTasks = new ArrayList<>();
            long pos = start;
            for (int i = 0; i < 100; i++) {
                long lastOne = pos + step;
                if (lastOne > end) {
                    lastOne = end;
                }
                Main subTask = new Main( pos, lastOne );
                pos += step + 1;
                subTasks.add( subTask );
                subTask.fork();
            }
            for (Main t : subTasks) {
                sum += t.join();
            }
        }
        return sum;
    }
}

猜你喜欢

转载自blog.csdn.net/HuaLingPiaoXue/article/details/89928579
今日推荐