Java进阶之线程池ForkJoinPool :用法实例(一百四十七)

简介: CSDN博客专家、《Android系统多媒体进阶实战》一书作者

博主新书推荐:《Android系统多媒体进阶实战》🚀
Android Audio工程师专栏: Audio工程师进阶系列原创干货持续更新中……】🚀
Android多媒体专栏: 多媒体系统工程师系列原创干货持续更新中……】🚀
推荐1:车载系统实战课:AAOS车载系统+AOSP14系统攻城狮入门视频实战课 🚀
推荐2:HIDL与AIDL实战课:Android14 Binder之HIDL与AIDL通信实战课 🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮

欢迎关注Android系统攻城狮

🌻1. 前言

本篇目的:Java线程池之ForkJoinPool:用法实例

🌻2. Java线程池ForkJoinPool介绍

  1. 基本概念
    ForkJoinPool是Java并发包提供的支持分治并行计算的线程池,基于工作窃取算法,适合递归任务拆分。

  2. 功能
    提供提交ForkJoinTask、invoke、execute、invokeAll等方法,支持RecursiveTask、RecursiveAction两种任务类型。

  3. 使用限制
    任务需可拆分且避免阻塞,否则降低并行度。

  4. 性能特性
    工作窃取平衡负载,线程数默认等于CPU核数,可设置parallelism调整。

  5. 使用场景
    大数据并行计算、归并排序、MapReduce框架、图形处理等。

🌻3. 代码实例

🌻3.1 使用ForkJoinPool并行计算累加和
  1. 应用场景
    并行求1到n的和。

  2. 用法实例

    import java.util.concurrent.*;
    
    public class SumTask extends RecursiveTask<Long> {
        private final int start, end;
        private static final int THRESHOLD = 1000;
    
        public SumTask(int start, int end) {
            this.start = start;
            this.end = end;
        }
    
        protected Long compute() {
            if (end - start <= THRESHOLD) {
                long sum = 0;
                for (int i = start; i <= end; i++) sum += i;
                return sum;
            }
            int mid = (start + end) >>> 1;
            SumTask left = new SumTask(start, mid);
            SumTask right = new SumTask(mid + 1, end);
            left.fork();
            return right.compute() + left.join();
        }
    
        public static void main(String[] args) {
            ForkJoinPool pool = new ForkJoinPool();
            long result = pool.invoke(new SumTask(1, 10000));
            System.out.println(result);
        }
    }
    

    输出:
    50005000

🌻3.2 使用ForkJoinPool并行排序数组
  1. 应用场景
    并行归并排序。

  2. 用法实例

    import java.util.concurrent.*;
    
    public class MergeSort extends RecursiveAction {
        private final int[] arr;
        private final int left, right;
    
        public MergeSort(int[] arr, int left, int right) {
            this.arr = arr;
            this.left = left;
            this.right = right;
        }
    
        protected void compute() {
            if (left < right) {
                int mid = (left + right) >>> 1;
                invokeAll(new MergeSort(arr, left, mid), new MergeSort(arr, mid + 1, right));
                merge(left, mid, right);
            }
        }
    
        private void merge(int l, int m, int r) {
            int[] tmp = new int[r - l + 1];
            int i = l, j = m + 1, k = 0;
            while (i <= m && j <= r) tmp[k++] = arr[i] < arr[j] ? arr[i++] : arr[j++];
            while (i <= m) tmp[k++] = arr[i++];
            while (j <= r) tmp[k++] = arr[j++];
            System.arraycopy(tmp, 0, arr, l, tmp.length);
        }
    
        public static void main(String[] args) {
            int[] data = {5, 3, 8, 6, 2, 7, 4, 1};
            ForkJoinPool.commonPool().invoke(new MergeSort(data, 0, data.length - 1));
            for (int v : data) System.out.print(v);
        }
    }
    

    输出:
    12345678

🌻3.3 使用ForkJoinPool并行统计文件行数
  1. 应用场景
    递归统计目录下所有文件总行数。

  2. 用法实例

    import java.io.*;
    import java.nio.file.*;
    import java.util.concurrent.*;
    
    public class LineCounter extends RecursiveTask<Long> {
        private final Path path;
    
        public LineCounter(Path path) {
            this.path = path;
        }
    
        protected Long compute() {
            try {
                if (Files.isRegularFile(path)) {
                    return Files.lines(path).count();
                } else if (Files.isDirectory(path)) {
                    try (var s = Files.list(path)) {
                        return s.map(LineCounter::new)
                                .collect(ForkJoinTask::invokeAll,
                                         (a, b) -> a.add(b.join()),
                                         (a, b) -> a + b);
                    }
                }
            } catch (IOException ignored) {}
            return 0L;
        }
    
        public static void main(String[] args) {
            ForkJoinPool pool = ForkJoinPool.commonPool();
            long lines = pool.invoke(new LineCounter(Paths.get("src")));
            System.out.println(lines);
        }
    }
    

    输出示例:
    1234

🌻3.4 线程池ForkJoinPool总结

关键词功能描述典型应用
ForkJoinPool分治并行线程池大数据累加、归并排序、文件统计
RecursiveTask有返回结果任务并行求和、统计
RecursiveAction无返回结果任务并行排序、图形处理
commonPool全局共享池无需显式创建即可使用
parallelism并行度参数控制线程数量提升或降低吞吐量
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Android系统攻城狮

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

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

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

打赏作者

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

抵扣说明:

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

余额充值