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

为什么stream parallel()不使用所有可用的线程?

史同化
2023-03-14
java prettyprint-override">    @Test
    public void testParallelStream() throws Exception {
        final int REQUESTS = 100;
        ForkJoinPool forkJoinPool = null;
        try {
            // new ForkJoinPool(256): same results for all tried values of REQUESTS
            forkJoinPool = new ForkJoinPool(REQUESTS);
            forkJoinPool.submit(() -> {

                IntStream stream = IntStream.range(0, REQUESTS);
                final List<String> result = stream.parallel().mapToObj(i -> {
                    try {
                        System.out.println("request " + i);
                        Thread.sleep(1000);
                        return Integer.toString(i);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }).collect(Collectors.toList());
                // assertThat(result).hasSize(REQUESTS);
            }).join();
        } finally {
            if (forkJoinPool != null) {
                forkJoinPool.shutdown();
            }
        }
    }

output指示在1s暂停之前执行16个流元素,然后再执行16个元素,依此类推。因此,即使forkjoinpool是用100个线程创建的,也只有16个线程被使用。

当我使用超过23个线程时,就会出现这种模式:

1-23 threads: ~1s
24-35 threads: ~2s
36-48 threads: ~3s
...
System.out.println(Runtime.getRuntime().availableProcessors());
// Output: 4

共有1个答案

田宇
2023-03-14

由于流实现对fork/join池的使用是一个实现细节,迫使它使用不同的fork/join池的技巧也没有文档化,而且似乎是偶然的,即有一个硬编码的常量决定实际的并行度,这取决于默认池的并行度。所以最初并没有预见到使用不同的池。

但是,已经认识到使用具有不适当的目标并行性的不同池是一个bug,即使这个把戏没有文档化,请参见JDK-8190974。

它已经在Java ;10中被修复,并被备份到Java ;8,update ;222。

因此,一个简单的解决方案世界正在更新Java版本。

您还可以更改默认池的并行性,例如。

System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "100");

在执行任何fork/join活动之前。

 类似资料:
  • 将并行流执行提交到您自己的forkJoinpool:yourfjp.submit(()->stream.parallel().foreach(doSomething)); 所以,我这样做了: 我创建了一组线程名,以查看创建了多少线程,并记录了池中活动线程的数量,这两个数字都不超过16,所以这意味着这里的并行度不超过16(为什么甚至是16?)。如果我不使用forkJoinPool,我得到4作为并行度

  • 当我运行以下代码时,8个可用线程中只有2个运行,有人能解释为什么会这样吗?我如何以这样一种方式更改代码,它将利用所有8个线程? 处理器:8 [main]向1 [main]树发送命令,其中数据1为真 [main]向6 [forkjoinpool.commonpool-worker-2]发送命令到5 [main]树,其中数据6为真 [forkjoinpool.commonpool-worker-2]树

  • null 只使用数据类型有什么特别的缺点吗? 使用数据类型代替数据类型有意义吗?

  • 我在Google DataProc集群上运行spark作业。但Spark似乎没有使用集群中所有可用的vCore,如下所示 基于这样和这样的其他一些问题,我已经设置了集群以使用来考虑资源分配的vcpus和内存 但当我提交带有自定义spark标志的作业时,看起来YARN不尊重这些自定义参数,默认使用内存作为资源计算的标准 能帮助某人弄清楚这里发生了什么?

  • 我有一个GridLayout(我以编程方式向其中添加子元素)。 结果很糟糕,因为GridLayout没有填满所有可用空间。 这就是结果: 这是我的XML:

  • 本文向大家介绍为什么要使用多线程?相关面试题,主要包含被问及为什么要使用多线程?时的应答技巧和注意事项,需要的朋友参考一下 先从总体上来说: 从计算机底层来说:线程可以比作是轻量级的进程,是程序执行的最小单位,线程间的切换和调度的成本远远小于进程。另外,多核 CPU 时代意味着多个线程可以同时运行,这减少了线程上下文切换的开销。 从当代互联网发展趋势来说:现在的系统动不动就要求百万级甚至千万级的并