并发编程--Fork/Join框架

一、简介

        Fork/Join框架是 Java 7 提供的一个用于并行 行任 的框架,是一个把大任 分割成若干
个小任 ,最 终汇总 每个小任 务结 果后得到大任 务结 果的框架。
        我们 再通 Fork Join 两个 单词 来理解一下 Fork/Join 框架。 Fork 就是把一个大任 切分
若干子任 并行的 行, Join 就是合并 些子任 果,最后得到 个大任
果。比如 1+2+…+10000 ,可以分割成 10 个子任 ,每个子任 别对 1000 个数 行求和,
终汇总这 10 个子任 果。

二、流程

1.分割任务:首先我们需要有一个fork类来把大任务分割成子任务,有可能子任务还是很大,所以还需要不停地分割,直到分割出的子任务足够小。

2.执行任务并合并结果。分割的子任务分别放在双端队列里,然后几个启动线程分别从双端队列里获取任务执行。子任务执行完的结果都统一放在一个队列里,启动一个线程从队列里拿数据,然后合并这些数据。

 三、工作窃取算法

工作窃取( work-stealing )算法是指某个 线 程从其他 列里窃取任 执行。
假如我 需要做一个比 大的任 ,可以把 个任 分割 若干互不依赖 的子任 了减少 线 争,把 些子任 放到不同的 列里,并 每个队列 建一个 独的 线 程来 列里的任 线 程和 列一一 对应 。比如 A 线 负责处 A 队列里的任 。但是,有的 线 程会先把自己 列里的任 干完,而其他 线 对应 列里 有 任务 等待 理。干完活的 线 程与其等着,不如去帮其他 线 程干活,于是它就去其他 线 程的 列里窃取一个任务 行。
而在 这时 访问 同一个 列,所以 了减少窃取任 务线 程和被窃取任务线 程之 争,通常会使用双端 列,被窃取任 务线 程永 从双端 列的 部拿任务执 行,而窃取任 线 程永 从双端 列的尾部拿任 务执

 优点:充分利用线行并行算,减少了线争。

缺点:在某些情况下还是存在争,比如双端列里只有一个任务时。并且该算法会消耗了更多的系统资源,比如建多个线程和多个双端列。

四、ForkJoin应用

Fork/Join使用两个来完成分治的操作

1.ForkJoinTask

要使用ForkJoin框架,必首先建一个ForkJoin。它提供在任务中执fork()join()操作的机制。通常情况下,我不需要直接ForkJoinTask,只需要继承它的子类Fork/Join框架提供了以下两个子

·RecursiveAction :用于没有返回 果的任
·RecursiveTask :用于有返回 果的任
核心方法:

fork():在当前线程运行的线程池中创建一个子任务;join():模块子任务完成的时候返回任务结果;invoke():执行任务,也可以实时等待最终执行结果

2.ForkJoinPool

线程池最大的特点就是分叉(fork)合并(join)模式,将一个大任务拆分成多个小任务,并行执行,再结合工作窃取算法提高整体的执行效率,充分利用CPU资源。

3.实例


    private static final Integer MAX = 200;

    static class MyForkJoinTask extends RecursiveTask<Integer> {
        // 子任务开始计算的值
        private Integer startValue;

        // 子任务结束计算的值
        private Integer endValue;

        public MyForkJoinTask(Integer startValue , Integer endValue) {
            this.startValue = startValue;
            this.endValue = endValue;
        }

        @Override
        protected Integer compute() {
            // 如果条件成立,说明这个任务所需要计算的数值分为足够小了
            // 可以正式进行累加计算了
            if(endValue - startValue < MAX) {
                System.out.println("开始计算的部分:startValue = " + startValue + ";endValue = " + endValue);
                Integer totalValue = 0;
                for(int index = this.startValue ; index <= this.endValue  ; index++) {
                    totalValue += index;
                }
                return totalValue;
            }
            // 否则再进行任务拆分,拆分成两个任务
            else {
                MyForkJoinTask subTask1 = new MyForkJoinTask(startValue, (startValue + endValue) / 2);
                subTask1.fork();
                MyForkJoinTask subTask2 = new MyForkJoinTask((startValue + endValue) / 2 + 1 , endValue);
                subTask2.fork();
                return subTask1.join() + subTask2.join();
            }
        }
    }

    public static void main(String[] args) {
        // 这是Fork/Join框架的线程池
        ForkJoinPool pool = new ForkJoinPool();
        ForkJoinTask<Integer> taskFuture =  pool.submit(new MyForkJoinTask(1,1001));
        try {
            Integer result = taskFuture.get();
            System.out.println("result = " + result);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace(System.out);
        }
    }

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
学习Java并发编程是一项需要投入大量时间和精力的任务,但它在现代软件开发中是不可或缺的。通过深入学习线程、同步和异步、互斥和死锁、线程安全性、并发编程模型以及Java并发包等内容,您可以成为一名更加优秀的编程专家。 对于初学者来说,Java并发编程可能会显得晦涩难懂,并且涉及了许多新技术。在学习这一领域之前,建议掌握好相关的理论知识,并打好基础。只有在掌握了基础知识后,才能更好地理解和应用更高层次的概念。 在进行Java并发编程的训练时,以下是一些建议: 1. 了解并掌握Java中的线程机制和线程生命周期。 2. 学习如何使用同步和异步机制来处理并发编程中的数据共享和通信问题。 3. 理解并学习如何使用锁、互斥和死锁的概念以及如何避免它们。 4. 熟悉线程安全性的概念和相关的技术,如volatile关键字和Atomic类。 5. 学习并理解Java提供的并发编程模型,如线程池和Fork/Join框架。 6. 了解并掌握Java并发包中提供的各种类和工具,如Semaphore、CountDownLatch和CyclicBarrier等。 通过不断学习和练习,并发编程的技能会得到提升。建议您多实践编写并发程序,通过解决实际问题来加深对并发编程的理解。祝您在学习Java并发编程的过程中取得成功!<span class="em">1</span><span class="em">2</span> #### 引用[.reference_title] - *1* *2* [如何学习Java并发编程](https://blog.csdn.net/weixin_42080277/article/details/129785094)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值