首页 > 其他分享 >ForkJoinPool实践

ForkJoinPool实践

时间:2023-08-03 11:07:50浏览次数:36  
标签:end int ForkJoinPool 实践 util start java

最近在看一本15年出版的《Java并发编程的艺术》一书,其中看到并发编程时间部分的ForkJoinPool功能时,突然发现这个功能实际使用上就是把一个大任务分成多个小的子任务,然后使用多个线程完成。

这个场景跟我之前写过的自定义Java自定义异步功能实践有点异曲同工之妙,只不过这里有有个子任务的概念,多个任务执行结果是具有相关性的。资料指出ForkJoinPool比较适合计算密集型的任务。

性能测试中QPS取样器和RT取样器中,有这样一个使用场景,在用例执行过程中,我想了解一下当前用例执行的QPS和RT信息,就需要有个触发开关,开始收集这些数据,等某一个终止条件被触发,结束收集,然后计算结果。在用例QPS超过10万的情况下,单次收集的数据可能会超过100万,计算QPS和RT就非常适合ForkJoinPool来完成。

如果一直实时展示或者上报这些信息的话,也可以使用ForkJoinPool来完成计算功能。这里还有另外的方案来实现,如果只是得到QPS和RT数据的话,比ForkJoinPool更加合适,这里先不分享了。

ForkJoinPool API相比较ExecutorService还是比较简单的。主要的功能3个:创建任务的ForkJoinPool、创建任务分配规则和收集任务结果。

下面我以一个数组求和的Demo演示一下ForkJoinPool的功能。

首先我们需要定义一个ForkJoinPool,通常使用java.util.concurrent.ForkJoinPool#ForkJoinPool(int)或者java.util.concurrent.ForkJoinPool#commonPool这两个方法其中之一,如果你使用JDK 7及以前的版本,第二个API是不存在的。

翻看源码之后,看起来ForkJoinPool构造方法参数还是挺多的,如果都要自定义比较麻烦也是没多大必要的,所以我就选上面提到的第一种API来创建ForkJoinPool。

然后我们要创建一个任务类实现任务分配规则,首先继承java.util.concurrent.RecursiveTask实现java.util.concurrent.RecursiveTask#compute方法。

拆分任务的思路如下:使用两个int属性,标记List中需要求和片段索引。这样每次分配任务的时候,只需要改变索引值即可。将一个很长的List求和分成N个小片段求和。

类代码设计如下:

import com.funtester.frame.SourceCode
import groovy.util.logging.Log4j2

import java.util.concurrent.ForkJoinPool
import java.util.concurrent.RecursiveTask

@Log4j2
class ForkJoinT extends RecursiveTask<Integer> {

    static def data = 1..100 as List

    int start
    int end

    ForkJoinT(int start, int end) {
        this.start = start
        this.end = end
    }

    @Override
    protected Integer compute() {
        if (end - start < 5) {
            sum(start, end)
        } else {
            def middle = ((start + end) / 2) as int
            def left = new ForkJoinT(start, middle)
            def right = new ForkJoinT(middle + 1, end)
            left.fork()
            right.fork()
            left.join() + right.join()
        }
    }

    /**
     * 片段求和
     * @param i
     * @param k
     * @return
     */
    static def sum(int i, int k) {
        SourceCode.range(i, k + 1).map(data::get).sum()
    }

}

总体感觉java.util.concurrent.RecursiveTask#compute方法写起来有点像递归,思路明确了以后还是很流畅的。

先来个高斯求和,下面是测试代码:

    static void main(String[] args) {
        def pool = new ForkJoinPool(5)
        def t = new ForkJoinT(0, data.size() - 1)
        pool.submit(t)
        log.info("sum: {}", t.get())
    }

控制台输出:

22:30:42.725 main sum: 5050

标签:end,int,ForkJoinPool,实践,util,start,java
From: https://blog.51cto.com/FunTester/6947068

相关文章

  • GPU 容器虚拟化新能力发布和全场景实践
    今天给大家分享的主题是百度智能云在「GPU容器虚拟化」方面的最新进展和全场景实践,希望通过这次分享和大家一起探讨如何在实际业务场景更好的应用GPU容器虚拟化技术。本次分享将首先介绍百度智能云GPU容器虚拟化2.0的升级变化,然后介绍新版本中的技术实现方法并演示具体功能,......
  • 火山引擎DataLeap的Data Catalog系统搜索实践 (上)
    更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群摘要火山引擎大数据研发治理套件DataLeap的DataCatalog系统通过汇总和组织各种元数据,解决了数据生产者梳理数据、数据消费者找数和理解数的业务场景,其中搜索是DataCatalog的主要功能之一。本文......
  • 火山引擎DataLeap的Data Catalog系统搜索实践 (上)
    更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群摘要火山引擎大数据研发治理套件DataLeap的DataCatalog系统通过汇总和组织各种元数据,解决了数据生产者梳理数据、数据消费者找数和理解数的业务场景,其中搜索是DataCatalog的主要功能之......
  • 8 个线程池最佳实践和坑!使用不当直接生产事故!!
    这篇文章我会简单总结一下我了解的使用线程池的时候应该注意的坑以及一些优秀的实践。拿来即用,美滋滋!内容概览:Java指南:https://java-family.cn1、正确声明线程池线程池必须手动通过 ThreadPoolExecutor 的构造函数来声明,避免使用Executors 类创建线程池,会有OOM风险。Ex......
  • Docker部署项目实践
    上一篇文件介绍了《Docker基础》,介绍类介绍如何使用docker发布java项目。一、项目打包首先,Docker部署项目前,先将项目打包好,比如达成jar文件,最好直接测试jar是否可运行,这里指定了端口1java-jaryour-app.jar--server.port=8081然后,将打包好的文件放到服务器指定位置 ......
  • Arthas学习实践
    Arthas是一款线上jvm诊断工具,能够查看java应用到资源使用信息、函数调用统计等,同时还能在不停止jvm运行的情况下,修改运行时代码,查看方法的调用、入参、返回值等。Arthas的关键技术有两方面:java-agent机制与字节码修改(与rasp相同)Arthas采用命令行的方式与用户交互,Arthas的安装过......
  • 进程注入如何通过调用栈,使用ML分类来检测——非常值得借鉴,待实践
    4、MachineLearningtoUltimatelyDefeatAdvancedRansomwareThreatsRSA2022的这个分享主题核心讲解了进程注入如何通过调用栈,使用ML分类来检测。当然,勒索的其他本质特征例如文件加密等没有提到。但是其进程注入的检测值得重点关注。Ryukasthemostadvancedformofransomw......
  • 活动预告 | 中国数据库联盟(ACDU)中国行第二站定档杭州,邀您探讨数据库技术与实践!
    数据库技术一直是信息时代中不可或缺的核心组成部分,随着信息量的爆炸式增长和数据的多样化,其重要性愈发凸显。作为中国数据库联盟(ACDU)的品牌活动之一,【ACDU中国行】在线下汇集数据库领域的行业知名人士,共同探讨数据库前沿技术及其应用,促进行业发展和创新,同时也为开发者们提供一个......
  • YApi怎么测试接口: 最佳实践
    接口测试为什么要接口测试?你想想,你们后端团队写了几百个接口,兴高采烈地,直接部署上线,你们开开心心下班去。等到晚上的时候,你发现你们的接口好几个都崩了,这导致了你们产品损失了一大批用户,那个时候你会后悔,后悔啥呢?后悔接口写完后,没有进行 接口测试 。要怎么测试?其实现在市面上已经......
  • Java实践项目 - 商品分类
    Smiling&Weeping----好想回到那个拉钩许诺的年代 1.1商品分类的思路:一次性查询三级分类(一级为美味麒麟榜,二级为闭眼入,第三级为商品)优点:只需要一次查询,根据一级分类显示二级分类是响应较快缺点:数据库查询效率较低,页面首次加载速......