当前位置: 首页 > 知识库问答 >
问题:

在考虑将外部流并行化之前,内部并行流会被完全并行处理吗?

楚威
2023-03-14

从这个链接中,我只部分了解到,至少在某一点上,java嵌套并行流存在问题。然而,我无法推导出以下问题的答案:

Java会先并行执行内部流,然后处理外部流吗?如果是,它是在编译时还是在运行时做出这个决定?如果在运行时,JIT是否足够聪明,能够意识到如果内部流中的元素(例如数百个)比核数(32个)多得多,那么它肯定应该使用所有32个核来处理内部流,然后再从外部流中移动下一个元素;但是,如果元素的数量很少(例如<32),那么从“下一个”外部流的元素中“并行处理”元素也是可以的。

共有1个答案

印辉
2023-03-14

也许下面的示例程序可以说明这个问题:

java prettyprint-override">IntStream.range(0, 10).parallel().mapToObj(i -> "outer "+i)
         .map(outer -> outer+"\t"+IntStream.range(0, 10).parallel()
            .mapToObj(inner -> Thread.currentThread())
            .distinct() // using the identity of the threads
            .map(Thread::getName) // just to be paranoid, as names might not be unique
            .sorted()
            .collect(Collectors.toList()) )
         .collect(Collectors.toList())
         .forEach(System.out::println);

当然,结果会有所不同,但我机器上的输出看起来类似于这样:

outer 0 [ForkJoinPool.commonPool-worker-6]
outer 1 [ForkJoinPool.commonPool-worker-3]
outer 2 [ForkJoinPool.commonPool-worker-1]
outer 3 [ForkJoinPool.commonPool-worker-1, ForkJoinPool.commonPool-worker-4, ForkJoinPool.commonPool-worker-5]
outer 4 [ForkJoinPool.commonPool-worker-5]
outer 5 [ForkJoinPool.commonPool-worker-2, ForkJoinPool.commonPool-worker-4, ForkJoinPool.commonPool-worker-7, main]
outer 6 [main]
outer 7 [ForkJoinPool.commonPool-worker-4]
outer 8 [ForkJoinPool.commonPool-worker-2]
outer 9 [ForkJoinPool.commonPool-worker-7]

我们在这里看到的是,对于我的机器,有8个核心,7个工作线程正在为工作做出贡献,为了利用所有核心,对于公共池,调用线程也将为工作做出贡献,而不是仅仅等待完成。您可以在输出中清楚地看到main线程。

这种行为背后有一个简单的理由。当外流的处理开始时,它并不知道它将是一个“外流”。它只是一个并行流,除了处理它之外,没有办法知道这是否是一个外部流,直到其中一个函数启动另一个流操作。但是将并行处理推迟到这一点是没有意义的,因为这一点可能永远不会到来。

此外,我强烈反对你的假设,“如果内部流首先完全并行地完成,它的性能会更好[…]”。我更希望它反过来,阅读,期望一个优点,完全按照它已经实现,对于典型的用例。但是,正如上一段所解释的,没有合理的方法来实现并行处理内部流的偏好。

 类似资料:
  • 我有一个相当复杂的过程,需要几个层次的嵌套for循环。 只针对一组特定的条件执行操作。换句话说:

  • 问题内容: 我有要并行处理的元素的集合。当我使用时,并行性有效。但是,当我使用时,它不会并行运行。 我写了一个代码样本来说明问题: 这是我在Windows 7上获得的输出 我们可以看到中的第一个元素必须在处理第二个元素之前完成。对于,第二个元素在第一个元素结束之前开始。 您能否告诉我是什么原因导致此问题,以及如何使用集合避免发生此问题? 问题答案: 我可以重现您看到的行为,其中并行性与您指定的fo

  • 我编写了两个功能文件,每个功能文件打开不同的浏览器URL,例如一个是open google。com和secnd一个开放的亚马逊。但事实并非如此。 两个浏览器都打开了谷歌。通用域名格式。此外,它不能与浏览器交互,任何编码到浏览器的操作都不会执行。此外,关闭第一个浏览器会导致第二个浏览器出现空指针异常。 cucumber版本6我从AbstractCucumberTesNG继承开始。然后我创建登录。功能

  • 相反,如果我从web服务器收集数据,为什么不直接使用相同的节点进行事件处理呢?这些操作已经由负载均衡器分布在节点上,我在web服务器上使用负载均衡器。我可以在相同的JVM实例上创建执行器,并将事件从web服务器异步发送到执行器,而不涉及任何额外的IO请求。我还可以监视web服务器中的执行器,并确保执行器处理了事件(至少一次或恰好一次处理保证)。通过这种方式,管理我的应用程序将容易得多,而且由于不需

  • 问题内容: 为什么下面的代码不输出任何输出,而如果我们删除parallel,则输出0、1? 尽管我知道理想情况下应该将限制放在不同的位置,但是我的问题与添加并行处理导致的差异更多有关。 问题答案: 真正的原因是 有序并行 是完整的屏障操作,如文档中所述: 保持并行管道的稳定性是相对昂贵的(要求操作充当一个完整的屏障,并具有大量缓冲开销),并且通常不需要稳定性。 “完全屏障操作”是指必须先执行所有上

  • 根据文档[1],我一直试图在Akka stream中并行化一个流,但由于某些原因,我没有得到预期的结果。 我遵循了留档中列出的步骤,我不认为我错过了什么。然而,我的流的计算都是按顺序一个接一个地发生的。 我错过了什么? [1] https://doc.akka.io/docs/akka/current/stream/stream-parallelism.html 示例输出 我希望看到两个计算同时进