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

Fork/Join解读

作者头像
一个风轻云淡
发布2023-10-15 11:12:22
1480
发布2023-10-15 11:12:22
举报
文章被收录于专栏:java学习javajava学习java
概念

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 之间的整数求和的任务

代码语言:javascript
复制
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 来执行

代码语言:javascript
复制
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

用图来表示

改进

代码语言:javascript
复制
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 来执行

代码语言:javascript
复制
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 

 用图来表示

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-09-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概念
  • 关键点
  • 使用
相关产品与服务
GPU 云服务器
GPU 云服务器(Cloud GPU Service,GPU)是提供 GPU 算力的弹性计算服务,具有超强的并行计算能力,作为 IaaS 层的尖兵利器,服务于深度学习训练、科学计算、图形图像处理、视频编解码等场景。腾讯云随时提供触手可得的算力,有效缓解您的计算压力,提升业务效率与竞争力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档