[实践总结] 通过累加求和来学习 分支/合并框架

分支/合并框架

分支/合并框架的目的是以 递归方式将可以并行的任务拆分成更小的任务,然后将每个子任务的结果合并起来生成整体结果。

它是ExecutorService接口的一个实现,它把子任务分配给线程池(称为ForkJoinPool)中的工作线程。

ForkJoinSumCalculator

java 复制代码
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
import java.util.stream.LongStream;

//继承RecursiveTask来创建可以用于分支/合并框架的任务
public class ForkJoinSumCalculator extends RecursiveTask<Long> {
    // ---------------------------框架的属性---------------------------
    public static final ForkJoinPool FORK_JOIN_POOL = new ForkJoinPool();

    // ---------------------------业务的属性---------------------------
    public static final long THRESHOLD = 10_000;  //不再将任务分解为子任务的数组大小
    private final long[] numbers;
    private final int start;
    private final int end;

    //公共构造函数 用于 创建主任务
    public ForkJoinSumCalculator(long[] numbers) {
        this(numbers, 0, numbers.length);
    }

    //私有构造函数 用于 以递归方式为主任务创建子任务
    private ForkJoinSumCalculator(long[] numbers, int start, int end) {
        this.numbers = numbers;
        this.start = start;
        this.end = end;
    }

    // 调用主任务入口
    public static long forkJoinSum(long n) {
        long[] numbers = LongStream.rangeClosed(1, n).toArray();
        ForkJoinTask<Long> task = new ForkJoinSumCalculator(numbers);
        return FORK_JOIN_POOL.invoke(task);
    }

    // 感觉像主管给不同人派活,然后收集结果
    @Override
    protected Long compute() {
        int length = end - start;
        if (length <= THRESHOLD) {
            //如果大小小于或等于阈值,顺序计算结果
            return computeSequentially();
        }

        ForkJoinSumCalculator leftTask = new ForkJoinSumCalculator(numbers, start, start + length / 2); //为数组的前一半求和
        leftTask.fork(); // 另起一个ForkJoinPool线程 异步执行 新创建的子任务

        ForkJoinSumCalculator rightTask = new ForkJoinSumCalculator(numbers, start + length / 2, end); //为数组的后一半求和
        Long rightResult = rightTask.compute(); // 当前线程继续执行后半部分任务

        Long leftResult = leftTask.join(); // 等leftTask执行完毕

        return leftResult + rightResult; // 收集2个子任务结果组合
    }

    // 最底层的串行计算
    private long computeSequentially() {
        long sum = 0;
        for (int i = start; i < end; i++) {
            sum += numbers[i];
        }
        return sum;
    }
}

使用

java 复制代码
ForkJoinSumCalculator.forkJoinSum(10_000_000L)

# 结果
50000005000000

-----------------------------------------------------------------------------读书笔记摘自 书名:Java 8实战 作者:英 Raoul-Gabriel Urma 意 Mario Fusco 英 Alan M

相关推荐
m4Rk_7 小时前
【论文阅读】Agent 记忆机制(83):Inside Out——用可演化 PersonaTree 构建 Agent 的核心长期记忆
论文阅读·人工智能·学习·开源·github
不会就选b7 小时前
算法日常・每日刷题--<贪心>25
数据结构·算法
EatFan8 小时前
Spring Boot 4 落地观察:从 yudao-cloud、matecloud、JPower 看国产脚手架的升级路线与迁移清单
java·spring boot·后端·spring cloud·微服务·后端开发·jdk 21
Maiko Star8 小时前
* LangChain 提示词模板详解:ChatPromptTemplate 的使用与高级特性
java·人工智能·langchain
鬓戈8 小时前
Rust 语言与 AI 应用生态调研及学习路径
人工智能·学习·rust
传奇开心果编程8 小时前
【SwiftUI娓娓道来】第3课:让界面活起来——交互与动画指南
学习·macos·ui·ios·swiftui·swift
xian_wwq9 小时前
【学习笔记】等保合规安全基线核查实战
笔记·学习
传奇开心果编程9 小时前
【Jetpack Compose进阶学与练】第14课:系列收尾复习总结;Compose项目常见坑点汇总;学习路线与后续学习方向
android·学习·ui·kotlin·android jetpack
yangmu320310 小时前
发动机是怎么把油变成动力的:四冲程内燃机原理拆解
学习
m4Rk_10 小时前
【论文阅读】Agent 记忆机制(81):EMR——用情景记忆避免 Agent 在多步推理中反复绕圈
论文阅读·人工智能·学习·开源·github