ForkJoin的基本介绍和应用

ForkJoinPool 框架主要类:

ForkJoinPool 实现ForkJoin的线程池 - ThreadPool

  • ForkJoinWorkerThread  实现ForkJoin的线程

ForkJoinTask<V> 一个描述ForkJoin的抽象类 Runnable/Callable

  • RecursiveAction 无返回结果的ForkJoinTask实现Runnable
  • RecursiveTask<V> 有返回结果的ForkJoinTask实现Callable
  • CountedCompleter<T> 在任务完成执行后会触发执行一个自定义的钩子函数

ForkJoinPool 实现了Executor Service 接口

  • ExecutorService Java Executor框架的基础类
  • 其他ExecutorService的实现执行RunnableCallables任务
  •  ForkJoinPool执行ForkJoinTasks任务

可以通过Executors. newWorkStealPool创建ForkJoinPool


ForkJoinPool任务提交方式:

  1. public void execute(ForkJoinTask<?> task)
    public void execute(Runnable task)
  2. public <T> T invoke(ForkJoinTask<T> task)
  3. public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
  4. public <T> ForkJoinTask<T> submit(ForkJoinTask<T> task)
    public <T> ForkJoinTask<T> submit(Callable<T> task)
    public <T> ForkJoinTask<T> submit(Runnable task, T result)
    public ForkJoinTask<?> submit(Runnable task)

ForkJoinTask主要包括两个方法分别实现任务的分拆与合并:

fork()类似于Thread.start(),但是它并不立即执行任务,而是将任务放入工作队列中。

跟Thread.join()不同,ForkJoinTaskjoin()方法并不简单的阻塞线程,利用工作线程运行其他任务,当一个工作线程中调用join(),它将处理其他任务,直到注意到目标子任务已经完成。


ForkJoinTask3个子类:

RecursiveAction

无返回值的任务

RecursiveTask

有返回值的任务

CountedCompleter

完成任务后将触发其他任务


  • 还是之前的数组求和的例子
class LongSum extends RecursiveTask<Long> {

    static final int SEQUENTIAL_THRESHOLD = 1000;

    private int low;
    private int high;
    private int[] array;

    LongSum(int[] arr, int lo, int hi) {
        this.array = arr;
        this.low = lo;
        this.high = hi;
    }

    @Override
    protected Long compute() {
        //System.out.println(Thread.currentThread().getName());
        if (high - low <= SEQUENTIAL_THRESHOLD) {

            long sum = 0;
            for (int i = low; i < high; ++i) {
                sum += array[i];
            }

            return sum;

        } else {
            int mid = low + (high - low) / 2;
            LongSum left = new LongSum(array, low, mid);
            LongSum right = new LongSum(array, mid, high);
            left.fork();
            long rightAns = right.compute();
            long leftAns = left.join();
            return leftAns + rightAns;
        }
    }
}

 

public class LongSumMain {

	static long calcSum;

	public static void main(String[] args) throws Exception {
		int[] array = Utils.buildRandomIntArray(20000000);

 		calcSum = seqSum(array);
		System.out.println("seq sum=" + calcSum);

		LongSum ls = new LongSum(array, 0, array.length);
  		ForkJoinPool fjp  = new ForkJoinPool(4); // with number of threads to use

		ForkJoinTask<Long> result = fjp.submit(ls);
		System.out.println("forkjoin sum=" + result.get());

		fjp.shutdown();
		
	}


	static long seqSum(int[] array) {
		long sum = 0;
		for (int i = 0; i < array.length; ++i)
			sum += array[i];
		return sum;
	}
}
  • 里面很好的思想就是,一半的程序可以交由当前线程完成,不需要也另外开一个线程去处理。例子中每次分左半部分和右半部分,左半部分可以开线程去处理,而右半部分就可以当前线程来处理。
  • RecursiveAction的简单应用

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值