专栏首页悠扬前奏的博客Java并发-23.Fork/Join框架

Java并发-23.Fork/Join框架

  • 什么是Fork/Join框架
    • Fork把一个大任务切分成若干个子任务
    • Join把子任务的执行结果合并
  • 工作窃取算法
    • 是什么:某个线程从其他队列窃取任务来执行。
    • 双端队列实现,被窃取任务线程从头部拿任务执行,窃取任务线程从尾部拿任务执行
    • 优点:充分利用线程并行计算,减少线程竞争
    • 缺点:某些情况下存在竞争,消耗更多的系统资源
  • 框架设计
    • ForkJoinTask:创建ForkJoin任务,用于分割一般不需要直接继承它,而是继承它的子类:
      • RecursiveAction:没有返回结果的任务
      • RecursiveTask:有返回结果的任务
    • ForkJoinPool:执行任务并合并结果,ForkJoinTask通过它来执行
  • 使用:
package com.junzerg.threads;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.Future;
import java.util.concurrent.RecursiveTask;

/**
 * @author pengjunzhe
 */
public class CountTask extends RecursiveTask<Integer> {

    /**
     * 阈值
     */
    private static final int THRESHOLD = 2;
    private int start;
    private int end;

    public CountTask(int start, int end) {
        this.start = start;
        this.end = end;
    }

    @Override
    protected Integer compute() {
        int sum = 0;
        // 如果任务足够小,就直接计算任务
        boolean canComputer = (end - start) < THRESHOLD;
        if (canComputer) {
            for (int i = start; i <= end; i++) {
                sum += i;
            }
        } else {
            //如果任务大于阈值,就分裂成两个子任务来计算
            int middle = (end + start) / 2;
            CountTask leftTask = new CountTask(start, middle);
            CountTask rightTask = new CountTask(middle + 1, end);
            leftTask.fork();
            rightTask.fork();
            // 等待子任务执行完,得到结果
            int leftResult = leftTask.join();
            int rightResult = rightTask.join();
            sum = leftResult + rightResult;
        }
        return sum;
    }

    public static void main(String[] args) throws InterruptedException {
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        CountTask task = new CountTask(1,4);
        Future<Integer> result = forkJoinPool.submit(task);
        try{
            System.out.println(result.get());
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}
  • ForkJoinTask执行可能抛出异常,但是无法再主程序中获取
    • isCompletedAbnormally()方法检查是否已经抛出异常或者被取消了。
    • getException()方法可以获取异常,任务被取消了返回CancellationException,没有完成或者没有抛出异常返回null

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • LintCode-761. 最小子集

    给一非负整数数组. 取数组中的一部分元素, 使得它们的和大于数组中其余元素的和, 求出满足条件的元素数量最小值.

    悠扬前奏
  • 正则表达式-6.查找方向

    如果,需要一个模式,它包含的匹配本身并不返回,而是用于确认正确的匹配位置,它并不是匹配结果的一部分。这时就需要进行“前后查找”(一般而言,前后查找模式是相对于查...

    悠扬前奏
  • Pandas-14.统计函数

    悠扬前奏
  • Dubbo 的负载均衡策略:轮询策略

    Dubbo 中实现轮询策略的代码是:RoundRobinLoadBalance。这个策略和随机策略有一个比较大的差异在于,轮询策略需要知道上次是哪个实例被调用了...

    LieBrother
  • 贪心算法问题-LeetCode 55、45(贪心算法,跳跃问题)

    给定一个非负整数数组,你最初位于数组的第一个位置。 数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个位置。

    算法工程师之路
  • 一个以前没有注意的问题:java构造函数的执行顺序

    昨天在改一处代码时发现执行的过程和预想的不一样,仔细探究才发现是构造器执行顺序问题.(汗自己一下,基础不够扎实) 特地做了一些尝试然后把java构造器的执行顺...

    哲洛不闹
  • 一个以前没有注意的问题:java构造函数的执行顺序

    昨天在改一处代码时发现执行的过程和预想的不一样,仔细探究才发现是构造器执行顺序问题.(汗自己一下,基础不够扎实) 特地做了一些尝试然后把java构造器的执行顺...

    哲洛不闹
  • 一个以前没有注意的问题:java构造函数的执行顺序

    昨天在改一处代码时发现执行的过程和预想的不一样,仔细探究才发现是构造器执行顺序问题.(汗自己一下,基础不够扎实) 特地做了一些尝试然后把java构造器的执行顺...

    哲洛不闹
  • 一个以前没有注意的问题:java构造函数的执行顺序

    昨天在改一处代码时发现执行的过程和预想的不一样,仔细探究才发现是构造器执行顺序问题.(汗自己一下,基础不够扎实) 特地做了一些尝试然后把java构造器的执行顺...

    哲洛不闹
  • c语言实现TCP的socket通信

    ######################################## #makefile #############################...

    特立独行的猫a

扫码关注云+社区

领取腾讯云代金券