Java 为什么在这个代码段中,并行执行要比顺序执行花费更长的时间?

Java 为什么在这个代码段中,并行执行要比顺序执行花费更长的时间?,java,parallel-processing,java-stream,Java,Parallel Processing,Java Stream,以下代码的并行执行时间比顺序代码长。我知道并行流比顺序流更复杂,也更昂贵,我们不能指望并行流一直都能创造奇迹。我只是关心下面的代码 List<Integer> collect = IntStream.rangeClosed(1, 1000000) .unordered() .parallel() .filter(e -> e%7 == 0) .boxed() .collect(Collectors.toList()); long

以下代码的并行执行时间比顺序代码长。我知道并行流比顺序流更复杂,也更昂贵,我们不能指望并行流一直都能创造奇迹。我只是关心下面的代码

List<Integer> collect = IntStream.rangeClosed(1, 1000000)
    .unordered()
    .parallel()
    .filter(e -> e%7 == 0)
    .boxed()
    .collect(Collectors.toList());

    long endTime = System.nanoTime();

    collect.forEach(System.out::println);
    System.out.println(endTime - startTime);
List collect=IntStream.rangeClosed(110000)
.无序
.parallel()
.filter(e->e%7==0)
.boxed()
.collect(Collectors.toList());
long-endTime=System.nanoTime();
collect.forEach(System.out::println);
System.out.println(endTime-startTime);
输出:

  • 带顺序流:40227 795

  • 平行流:74656768

这条流有状态吗? 如果不是,那么为什么并行流需要更长的时间? 这背后的原因是什么?
对此是否有精确的猜测?

您正在并行处理某些内容的唯一事实并不总是意味着这将比顺序处理快。这是编程中一个相当复杂的主题。在C#中有一个关于这个问题的话题。但它也可以应用于Java


简而言之,创建新线程是一项非常昂贵的操作,创建它确实需要时间。此外,在多线程环境中工作需要所谓的上下文切换,这与通常有比实际内核更多的进程这一事实有关,因此它们在执行某些操作时需要共享内核,这也是相当昂贵的。您可以找到一些与任何特定编程语言都不相关的温和介绍,而是将重点放在一般问题上。

默认情况下,
Stream.parallel()
使用
ForkJoinPool.commonPool()
作为其线程池。该池中的线程是动态分配的。这意味着,如果单独运行上述代码,基准测试将包括ThreadFactory生成线程()所需的时间

在这种情况下,如果您:

  • 例如,通过在启动计时器之前执行另一个并行流操作来预热线程池
  • 增加线程工作负载的大小。您正在做的工作相当琐碎,因此(显然)需要流中超过一百万项才能显示其好处

请注意,
ForkJoinPool.commonPool()
的池中最多有(#cores-1)个线程,因此在不同的计算机上运行相同的测试可能会得到更好或更差的结果,但请记住,对于较小的工作负载,由于开销减少,更少的线程更有可能显示出好处。

1。2.并行执行具有更高的复杂性,它引入的开销只有在您知道自己在做什么,并且任务适合并行处理的情况下才能得到回报。你不能只是把事情平行化,然后期望它更快,这不是事情的运作方式。这能回答你的问题吗?