• 0
  • 0
分享

最近在看一本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

性能方面等我先研究一波JMH之后再来。


  • 【留下美好印记】
    赞赏支持
登录 后发表评论
+ 关注

热门文章

    最新讲堂

      • 推荐阅读
      • 换一换
          •   本文将结合作者项目实践,介绍如何将EXCEL文件通过python转换为XML,以方便导入到Testlink中(Testlink仅支持XML文件的导入),并且顺便介绍一下Python常见的错误及解决方案,希望对大家有所帮助。  声明:文中转换工具涉及的代码是借鉴了其他帖子上的一部代码,结合本文作者项目的实际情况,编写而成。  输出EXCEL格式的测试用例文件  模板  测试用例使用如下模板输出,保存为XXX.xlsx文件,例如命名case.xlsx。  部分字段解释  功能点  一般EXCEL文件的一个Sheet页代表一个模块,在一个模块内部分为多个功能点,通过一个或多个测试用例对每个功能点...
            12 12 1445
            分享
          •   提起外包公司,很多小伙伴都不是很看好,觉得外包公司没啥发展前途、受限很多、没有自主权......也因此认为在外包公司没办法让测试新手提高技能。  但这些担忧,真的都有道理吗?换句话说,这些担忧都是有根据的吗?今天,我们就来聊聊这个话题。  我的外包企业工作经历  在这个外包公司这个问题上,我认为主要还是取决于外包企业所服务的甲方公司究竟是谁。也就是说,外包和外包还是有区别的。根据这几年我在外包公司工作的经验来看,外包公司主要有这么两类:  人力外包企业  如果你所在的是人力外包公司,负责的是一家开放且重技术的甲方公司,就会让你觉得,你就是在甲方本公司工作。  不仅不会让你觉得没有前途、发展...
            0 0 1225
            分享
          • 软件测试概念:一、什么是软件测试?1、软件测试是指使用人工或者自动手段,来运行或测试某个系统的过程。其目的在于检验它是否满足规定的需求或弄清预期结果与实际结果之间的差别。二、一般的软件测试的应用场景有:APP、代码、WEB和小程序。三、软件测试的发展历程:软件测试从开始到现在,已经经历了三个阶段的发展,到现在正式第三阶段到第四阶段的过渡期;第一阶段:定义的软件测试,是去证明软件是正确的。在这种情况下,导致了很多异常的情况根本无法被发现,软件的质量都比较差,不稳定,很容易出问题;第二阶段:软件测试是去证明软件是错误的。软件测试就是去找软件存在的问题,虽然现在软件测试已经发展到第三阶段很久了,但是...
            0 0 752
            分享
          •   概述  从去年4月份开始,已经发现我们的提测版本质量存在问题,于是陆陆续续向上反馈希望通过自测环节来把控提测版本质量问题。  为此,经过前期的一些探索我们开展了如下工作成果,增加自测流程:  · 整体汇总单体测试测试点V1.0  · 通用测试checklist 清单  · 单体测试宣讲  问题分析  在经过上述实践后,我们发现了一些不足之处。从不同角度深入分析,我们意识到在某些方面仍需改进。  排除一些主观因素外,存在问题现象有2点:  1、不能匹配所有项目  部门大部分项目为web 项目,有些功能清单能覆盖到,有的项目非web型,并且调用第三方平台,针对这种...
            0 0 1113
            分享
          •       Prometheus      配置说明      在istio网格中,每个组件都会暴露一个提供metrics的endpoint。Prometheus可以从这些endpoints上抓取metrics(通过Prometheus配置文件来设置scraping,端口以及TLS等)。      为了采集整个网格的metrics,需要配置Prometheus scraping组件:控制面(istiod deployment)ingress和eg...
            0 0 1791
            分享
      • 51testing软件测试圈微信