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,并进行了优化。

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

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

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • CSS 颜色代码大全 CSS颜色对照表[通俗易懂]

    CSS 颜色代码大全 CSS颜色对照表[通俗易懂]转载地址:https://blog.csdn.net/u012117917/article/details/41604711HTML及CSS常用颜色英文词汇  黑色 银色 灰色 白色 茶色 红色 紫色 紫红 black silver gray white maroon …

    2022年5月17日
  • vr全景制作常用的app有哪些,vr全景拍摄真的难吗?[通俗易懂]

    ​现在互联网发展得很快,从2G网络逐渐进步到5G网络,线上的营销方式也逐渐从文字转变为图片营销。图像呈现出来的效果更能打动用户,也更能吸引用户的注意力,对成交更有帮助。vr全景图展示是很多企业都在使用的一种技术,提高用户的信任度,增强用户粘性。那么vr全景制作app有哪些和vr全景拍摄难吗?下面就给大家简单讲一下吧。一般来说,大多数摄影师都使用鱼眼镜头、单反相机设备来拍摄所需的vr全景图,操作方法比较简单,但是拍摄完我们还需要来处理这个图片,这些步骤就比较麻烦了。vr全景制作app有哪些关于

    2022年4月18日
  • springboot-mybatis多数据源的两种整合方法[通俗易懂]

    springboot-mybatis多数据源的两种整合方法[通俗易懂]springboot-mybatis整合多数据源简介:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;随着并发量的不断增加,显然单个数据库已经承受不了高并发带来的压力。一个项目使用多个数据库(无论是主从复制–读写分离还是分布式数据库结构)的重要性变得越来越明显。传统项目中(个人对传统项目的理解就是所有的业务模块都在一个tomcat中完成,多个相

    2022年6月24日
  • mysql 端口监听问题「建议收藏」

    mysql 端口监听问题「建议收藏」mysql启动了,用localhost可以连接,但是用127.0.0.1不能连接。可能的原因是:1、mysql为了增强安全性而跳过了端口监听,查看方法: 用mysql>SHOWVARIABLES; 或者mysql>SHOWVARIABLESLIKE’skip_networking’;  查看skip_networking,如果skip_networki

    2022年9月27日
  • 权重系数确定问题_如何确定权重系数例子

    权重系数确定问题_如何确定权重系数例子根据各个指标获得综合指标时,由于各个指标对综合指标的贡献度不同,相应权重也应不同,对综合指标贡献大的指标更重要,应该分配更大的权重。如何确定各个指标的权重,这里介绍两种方法:熵值法和pca确定权重。也

    2022年8月4日
  • @RequestParam注解使用

    @RequestParam注解使用1、作用:@RequestParam:将请求参数绑定到你控制器的方法参数上(是springmvc中接收普通参数的注解)2、语法:语法:@RequestParam(value=”参数名”,required=”true/false”,defaultValue=””)value:参数名required:是否包含该参数,默认为true,表示该请求路径中必须包含该参数,如果不包含就报…

    2022年6月30日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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