前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java7 Fork/Join框架

Java7 Fork/Join框架

原创
作者头像
HLee
修改2021-09-16 10:04:49
6530
修改2021-09-16 10:04:49
举报
文章被收录于专栏:房东的猫房东的猫

简介

ForkJoin框架是Java7 提供的把一个大任务分割成若干个小任务,最终汇总每一个任务结果后得到大任务结果的框架。ForkJoinPool继承AbstractExecutorService,实现了Executor,ExecutorService。ForkJoinPool用来实现工作窃取算法。

Fork/Join框架主要包含三个模块:

  • 线程池:Fork/Join Pool
  • 任务对象:Fork/Join Task
  • 执行任务线程:Fork/Join WorkerThread

工作窃取算法

fork:将一个大任务根据条件不断的分割为互不依赖的小任务,并将这些小任务放入不同的队列,每个工作线程维护一个任务队列,当自己维护的任务队列为空时随机从别的任务队列获取任务执行。

join:最后再将这些小任务的结果都放在一个统一的队列当中,最后启动一个工作线程从这个结果队列中取数据合并得到最终的结果。

工作窃取算法中分割任务和合并结果的思想和Hadoop的MapReduce编程模型一样,优点是充分提高程序的并行度,有效的减少了线程之间的竞争,但是也会消耗过多的系统资源。

分治算法

把一个复杂的问题分解成多个相似的子问题,然后再把子问题分解成更小的问题,直到问题简单到可以直接求解。而大数据框架mapReduce就是分治的实现。Fork、Join计算框架主要用于处理CPU型任务,主要包含分治任务线程池 ForkJoinPool和分治任务ForkJoinTask。

Fork/Join案例

需求:使用Fork/Join计算1-1000000和。当一个任务的计算数量大于3000的时候拆分任务,数量小于3000的时候就计算。

代码语言:javascript
复制
public class SumRecursiveTask extends RecursiveTask<Long> {

    /**
     * 定义一个临界拆分值
     * @return
     */
    private static final long THRESHOLD = 3000;
    private final long start;
    private final long end;

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

    @Override
    protected Long compute() {

        long length = end - start;
        if (length <= THRESHOLD) {
            // 任务不需要拆分,可以计算
            long sum = 0;
            for (long i = start; i <= end; i++) {
                sum += i;
            }
            System.out.println("计算:" + start + "--->" + end + "的结果为:" + sum);
            return sum;
        } else {
            // 数量大于预订,需要拆分
            long middle = (start + end)/2;
            System.out.println("拆分左边:" + start + "--->" + middle + ", 右边" + (middle + 1) + "--->" + end);

            SumRecursiveTask left = new SumRecursiveTask(start, middle);
            left.fork();

            SumRecursiveTask right = new SumRecursiveTask(middle + 1, end);
            right.fork();

            return left.join() + right.join();
        }
    }
}
代码语言:javascript
复制
@Test
public void test() {

    long start = System.currentTimeMillis();
    ForkJoinPool pool = new ForkJoinPool();

    SumRecursiveTask task = new SumRecursiveTask(1, 10000L);
    Long result = pool.invoke(task);
    System.out.println("result:" + result);

    long end = System.currentTimeMillis();
    System.out.println("总耗时:" + (end - start));
}

输出结果:

代码语言:javascript
复制
拆分左边:1--->5000, 右边5001--->10000
拆分左边:1--->2500, 右边2501--->5000
拆分左边:5001--->7500, 右边7501--->10000
计算:5001--->7500的结果为:15626250
计算:1--->2500的结果为:3126250
计算:2501--->5000的结果为:9376250
计算:7501--->10000的结果为:21876250
result:50005000
总耗时:6

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • 工作窃取算法
  • 分治算法
    • Fork/Join案例
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档