Fork/Join解读

目录

概念

关键点

使用


概念

Fork/Join 是 JDK 1.7 加入的新的线程池实现,它体现的是一种分治思想,适用于能够进行任务拆分的 cpu 密集型 运算

所谓的任务拆分,是将一个大任务拆分为算法上相同的小任务,直至不能拆分可以直接求解。跟递归相关的一些计 算,如归并排序、斐波那契数列、都可以用分治思想进行求解

Fork/Join 在分治的基础上加入了多线程,可以把每个任务的分解和合并交给不同的线程来完成,进一步提升了运 算效率

Fork/Join 默认会创建与 cpu 核心数大小相同的线程池

关键点

Fork/Join(分而治之)是一种并行计算模型,用于解决递归性的、可以被分解为更小子任务的问题。它是 Java 7 引入的一个特性,并在 Java.util.concurrent 包中提供了相应的类来支持。

Fork/Join 模型基于以下两个关键操作:

  1. Fork(分解):将一个大任务分解为若干个小任务,并把这些小任务放入工作队列中,等待被执行。

  2. Join(合并):对小任务的执行结果进行合并,得到大任务的最终结果。

Fork/Join 模型的核心思想是递归地将问题划分为更小的子问题,直到子问题足够简单,可以直接求解。然后通过合并子问题的结果,最终得到原始问题的解。

在 Java 中,Fork/Join 模型的实现主要依赖于以下两个类:

  1. ForkJoinPool:是线程池的实现,用于管理任务的执行。它允许创建一个工作线程组,每个线程都有自己的工作队列。任务会被分发给空闲的工作线程执行,如果一个线程的工作队列为空,它可以从其他线程的队列中窃取任务来执行。

  2. RecursiveTask RecursiveAction:这两个抽象类是用来表示可分解的任务的。RecursiveTask 用于返回结果的任务,而 RecursiveAction 则用于不返回结果的任务。我们需要继承这些类,并实现 compute() 方法来执行任务划分和合并操作。

典型的使用场景包括在计算密集型任务中,例如大规模数据处理、图像处理、并行排序等。

Fork/Join 模型利用任务的递归分解和合并,能够充分利用多核处理器的性能,并提供了一种简洁高效的并行计算方式。

使用

提交给 Fork/Join 线程池的任务需要继承 RecursiveTask(有返回值)或 RecursiveAction(没有返回值),例如下 面定义了一个对 1~n 之间的整数求和的任务

class AddTask extends RecursiveTask<Integer> {

    int n;

    public AddTask(int n) {
        this.n = n;
    }

    @Override

    public String toString() {
        return "{" + n + '}';
    }

    @Override
    protected Integer compute() {
        // 如果 n 已经为 1,可以求得结果了

        if (n == 1) {
            System.out.println("join()"+n);
          
            return n;
        }

        // 将任务进行拆分(fork)

        AddTask t1 = new AddTask(n - 1);
        t1.fork();
        System.out.println("fork()"+n+" "+ t1);

        // 合并(join)结果

        int result = n + t1.join();
        System.out.println("join()"+n+"+"+t1+"="+result );
        return result;
    }

}

然后提交给 ForkJoinPool 来执行

public class Test {
    public static void main(String[] args) {
        ForkJoinPool pool = new ForkJoinPool(4);
        System.out.println(pool.invoke(new AddTask(5)));

    }

}

输出

fork()3 {2}
fork()5 {4}
fork()2 {1}
fork()4 {3}
join()1
join()2+{1}=3
join()3+{2}=6
join()4+{3}=10
join()5+{4}=15
15

用图来表示

改进

class AddTask3 extends RecursiveTask<Integer> {

    int begin;
    int end;

    public AddTask3(int begin, int end) {
        this.begin = begin;
        this.end = end;
    }

    @Override

    public String toString() {
        return "{" + begin + "," + end + '}';
    }

    @Override

    protected Integer compute() {
        // 5, 5
        if (begin == end) {
            log.debug("join() {}", begin);
            return begin;
        }
        // 4, 5
        if (end - begin == 1) {
            log.debug("join() {} + {} = {}", begin, end, end + begin);
            return end + begin;
        }

        // 1 5
        int mid = (end + begin) / 2;

        // 3
        AddTask3 t1 = new AddTask3(begin, mid);

        // 1,3
        t1.fork();
        AddTask3 t2 = new AddTask3(mid + 1, end);
        // 4,5
        t2.fork();
        log.debug("fork() {} + {} = ?", t1, t2);
        int result = t1.join() + t2.join();
        log.debug("join() {} + {} = {}", t1, t2, result);
        return result;
    }
}

然后提交给 ForkJoinPool 来执行

public static void main(String[] args) {
 ForkJoinPool pool = new ForkJoinPool(4);
 System.out.println(pool.invoke(new AddTask3(1, 10)));
}

结果

[ForkJoinPool-1-worker-0] - join() 1 + 2 = 3

[ForkJoinPool-1-worker-3] - join() 4 + 5 = 9

[ForkJoinPool-1-worker-0] - join() 3

[ForkJoinPool-1-worker-1] - fork() {1,3} + {4,5} = ?

[ForkJoinPool-1-worker-2] - fork() {1,2} + {3,3} = ?

[ForkJoinPool-1-worker-2] - join() {1,2} + {3,3} = 6

[ForkJoinPool-1-worker-1] - join() {1,3} + {4,5} = 15 15 

 用图来表示

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个风轻云淡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值