ForkJoin 线程池[通俗易懂]

ForkJoin 线程池[通俗易懂]一、分而治之严格来讲,分而治之不算一种模式,而是一种思想。它可以将一个大任务拆解为若干个小任务并行执行,提高系统吞吐量。主要讲两个场景,Master-Worker模式,ForkJoin线程池。ForkJoin线程池是jdk7之后引入的一个并行执行任务的框架,其核心思想也是将任务分割为子任务,有可能子任务还是很大,还需要进一步拆解,最终得到足够小的任务。将分割出来的子任务放入双端队列中,然后几个启动线程从双端队列中获取任务执行。子任务执行的结果放到一个队列里,另起线程从队列中获取数据,合并结果。

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

一、分而治之

严格来讲,分而治之不算一种模式,而是一种思想。它可以将一个大任务拆解为若干个小任务并行执行,提高系统吞吐量。主要讲两个场景,Master-Worker 模式,ForkJoin 线程池。

ForkJoin 线程池是Jdk7之后引入的一个并行执行任务的框架。其核心思想是将任务分割为子任务,有可能子任务还是很大,还需要进一步拆解,最终得到足够小的任务。将分割出来的子任务放入双端队列中,然后几个启动线程从双端队列中获取任务执行。子任务执行的结果放到一个队列里,另起线程从队列中获取数据,合并结果。ForkJoin 线程池[通俗易懂]

二、ForkJoin 与传统线程池的区别

采用 “工作窃取”模式(work-stealing):当执行新的任务时,它可以将其拆分成更小的任务执行,并将小任务加到线程队列中,然后再从一个随机线程的队列中偷一个并把它放在自己的队列中。 相较于一般的线程池,ForkJoin 的优势体现在对其中包含的任务的处理方式上。在一般的线程池中,如果一个线程正在执行的任务由于某些原因无法继续运行,那么该线程会处于等待状态。而 ForkJoin,如果某个子问题由于等待另外一个子问题的完成而无法继续运行,那么处理该子问题的线程会主动寻找其他尚未运行的子问题来执行。这种方式减少了线程的等待时间,提高了性能。

三、案例

计算从 0 到 100L 的累加求和。CountTask 继承自 RecursiveTask,可以携带返回值。每次分解大任务,简单的将任务划分为 10 个等规模的小任务,并使用 fork() 提交子任务。在子任务中通过 THRESHOLD(门槛) 设置子任务分解的阈值,如果当前需要求和的总数大于 THRESHOLD,则子任务需要再次分解,如果子任务可以直接执行,则进行求和操作,返回结果。最终等待所有的子任务执行完毕,对所有结果求和。

public class CountTask extends RecursiveTask<Long> { 
   
    //任务分解的阈值
    private static final int THRESHOLD = 11;
    private long start;
    private long end;

    public CountTask(long start, long end) { 
   
        this.start = start;
        this.end = end;
    }

    public Long compute() { 
   
        long sum = 0;
        boolean canCompute = (end - start) < THRESHOLD;
        if (canCompute) { 
   
            for (long i = start; i <= end; i++) { 
   
                sum += i;
            }
        } else { 
   
            //分成100个小任务
            long step = (start + end) / 10;
            ArrayList<CountTask> subTasks = new ArrayList<CountTask>();
            long pos = start;
            for (int i = 0; i < 10; i++) { 
   
                long lastOne = pos + step;
                if (lastOne > end) { 
   
                    lastOne = end;
                }
                CountTask subTask = new CountTask(pos, lastOne);
                pos += step + 1;
                //将子任务推向线程池
                subTasks.add(subTask);
                subTask.fork();
            }

            for (CountTask task : subTasks) { 
   
                //对结果进行join
                sum += task.join();
            }
        }
        return sum;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException { 
   
        ForkJoinPool pool = new ForkJoinPool();
        // 累加求和 0 -> 100L
        CountTask task = new CountTask(0, 100L);
        ForkJoinTask<Long> result = pool.submit(task);
        System.out.println("sum result : " + result.get());
    }
}

ForkJoin 线程池使用一个无锁的栈来管理空闲线程,如果一个工作线程暂时取不到可用的任务,则可能被挂起。挂起的线程将被压入由线程池维护的栈中,待将来有任务可用时,再从栈中唤醒这些线程。Java8 的并行流就是基于 ForkJoin,并进行了优化

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/191575.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 【转载】lvs为何不能完全替代DNS轮询

    【转载】lvs为何不能完全替代DNS轮询

    2021年11月20日
  • macOS 安装lrzsz

    macOS 安装lrzszmac自带的终端是不支持lrzsz的,需要下载安装iterm2MacOS终端利器iTerm2安装homebrewbrew的MAC安装macOS安装lrzsz进入/usr/local/bin由于原作者下架了项目,我们只能手动新建脚本了,下面请无脑全部复制即可。1.创建iterm2-recv-zmodem.sh#!/bin/bashosascript-e…

  • 实例分割论文_图像实例分割

    实例分割论文_图像实例分割作者丨youtober@知乎(已授权)来源丨https://zhuanlan.zhihu.com/p/412675982编辑丨极市平台导读本文综述基于实例分割的最新进展和发展历程,首先介…

  • GridView利用CheckBox复选框列实现单选功能

    GridView利用CheckBox复选框列实现单选功能自Dev13.2开始,GridView提供了自带的复选框列,该功能能实现多选操作,方便了不少,那如果想把这个自带的复选框列做成单选,那就需要单独处理了。先补充一下,GridView的复选框列怎么设置,如下代码片段,只要设置前面两个属性即可在GridView看到有一列复选框(BandedGridView较老版本不支持这个功能,应该得在19.2或者20之后的版本才支持,具体可以看看自己的版本,如果设置无效,那么说明不支持)://设置显示复选框列gridview.Option

  • sqlserver数据库数据迁移_mysql 数据库迁移

    sqlserver数据库数据迁移_mysql 数据库迁移前言:在我们开发某些项目后,难免会遇到更换服务器,重新部署数据库的时候,那么问题来了?究竟怎么如何操作才能达到最佳效果;起源:(1):起初仅仅是为了测试用,所以迁移的时候不必把数据库中的数据全部迁移过去,仅仅需要数据库的架构即可;(2):某些时候需要更换服务器,那么此时已经在内部存储了大量数据了,此时只能把架构+数据全部迁移过来;解说:以本地“Login”数据库为例,帮助大…

    2022年10月19日
  • 常见的预测模型及算法「建议收藏」

    常见的预测模型及算法「建议收藏」如果得到一份数据集,任务是要预测出一系列的值,而在预测任务中,我们大多数都采用的是拟合的方法,这篇文字主要介绍三种预测方法时间序列分析,灰色预测模型,神经网络。时间序列分析时间序列也叫动态序列,数据是按时间和数值性成的序列。而时间序列分析有三种作用,大致可以描述为描述过去,分析规律,预测将来。接下来将会讲到三种模型(季节分解,指数平滑,ARIMA模型)。一般情况下时间序列的数值变化规律有四种…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号