Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么具有短curcuit操作的并行Java流计算流的所有元素,而序列流则不计算?_Java_Parallel Processing_Java 8_Java Stream_Short Circuiting - Fatal编程技术网

为什么具有短curcuit操作的并行Java流计算流的所有元素,而序列流则不计算?

为什么具有短curcuit操作的并行Java流计算流的所有元素,而序列流则不计算?,java,parallel-processing,java-8,java-stream,short-circuiting,Java,Parallel Processing,Java 8,Java Stream,Short Circuiting,考虑两种测试方法parallel()和sequential(): Threads.sleepSafe()是Thread.sleep()的一个简单包装器,如果传递了0,它将接受异常,并且什么也不做 运行测试方法时,结果如下: sequential start. working... 0 worked. 0 sequential done. parallel start. working... 1 working... 0 worked. 0 sleeping for 1000 ms ... sl

考虑两种测试方法parallel()和sequential():

Threads.sleepSafe()是Thread.sleep()的一个简单包装器,如果传递了0,它将接受异常,并且什么也不做

运行测试方法时,结果如下:

sequential start.
working... 0
worked. 0
sequential done.

parallel start.
working... 1
working... 0
worked. 0
sleeping for 1000 ms ...
slept for 1000 ms.
worked. 1
parallel done.
sequential()
的操作与我预期的一样,但是
parallel()
没有: 我希望
parallel()
中的
findAny()
work()
第一次返回时返回(即,对于值0,因为它不睡眠),但它只在值1的
work()
完成后返回

为什么?


有没有一种方法可以使
findAny()
work()
第一次返回时立即返回?

如果需要并行流,那么是的,它将同时调用
work
方法数次

请注意,如果并行流有1000个元素并使用5个线程,那么并行流最多会调用
work
,而不是1000次


如果只想调用一次
work
,则使用顺序流。

如果想要并行流,则是,它将同时调用
work
方法数次

请注意,如果并行流有1000个元素并使用5个线程,那么并行流最多会调用
work
,而不是1000次


如果只想调用
work
一次,则使用顺序流。

并行模式下的流API基于一个范例,默认情况下使用maxX线程(其中X等于可用处理器的数量)。如果要增加迭代次数,可以检查此规则

通常,并行流的默认线程池计数可以通过两种方式进行自定义:

  • 将并行流执行提交到您自己的ForkJoinPool:
    yourFJP.submit(()->stream.parallel().forEach(soSomething))
  • 使用系统属性更改公共池的大小:
    system.setProperty(“java.util.concurrent.ForkJoinPool.common.parallelism”,“20”)
    以获得20个线程的目标并行性
有没有办法让findAny()在work()第一次返回时立即返回


根据ForkJoin算法的思想,答案基本上是否定的。它“等待”所有线程完成它们的工作。但如前所述,您可以将工作人员的数量限制为单个工作人员。显然,它没有场景,因为这种方法类似于顺序执行,冗余操作会增加额外的开销。

并行模式下的流API基于一种范例,默认情况下使用maxX线程(其中X等于可用处理器的数量)。如果要增加迭代次数,可以检查此规则

通常,并行流的默认线程池计数可以通过两种方式进行自定义:

  • 将并行流执行提交到您自己的ForkJoinPool:
    yourFJP.submit(()->stream.parallel().forEach(soSomething))
  • 使用系统属性更改公共池的大小:
    system.setProperty(“java.util.concurrent.ForkJoinPool.common.parallelism”,“20”)
    以获得20个线程的目标并行性
有没有办法让findAny()在work()第一次返回时立即返回


根据ForkJoin算法的思想,答案基本上是否定的。它“等待”所有线程完成它们的工作。但如前所述,您可以将工作人员的数量限制为单个工作人员。显然,它不会造成任何场景,因为这种方法类似于顺序执行,冗余操作会增加额外的开销。

并行流仍然支持短路,但如果所有线程都将其工作延迟到线程,则使用并行流没有任何好处处理以前的元素时,确认操作尚未结束

因此,只要正确组装最终结果(即丢弃多余的元素),并行流处理的元素数量超出需要,这是预期的行为

这只是你的例子,只包含两个元素,我们只处理了一个元素,超出了需要,可以解释为“所有元素都已处理”

当元素的数量很小和/或实际操作是在流的第一个元素中找到可以预测的东西时,并行处理通常没有什么好处。如果你做这样的事情,事情会变得更有趣

IntStream.range(0, 2000).parallel()
    .map(i -> { LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(50)); return i;})
    .filter(i->i%397==396)
    .findAny();

请注意,终端操作将在返回最终结果之前等待所有工作线程的完成,因此,当在找到结果之前已开始对元素进行求值时,该元素的处理将完成。这是故意的。它确保当应用程序代码在流操作后继续运行时,不会同时访问源集合或lambda表达式访问的其他数据

与之相比:

在几乎所有情况下,终端操作都是急切的,在返回之前完成对数据源的遍历和对管道的处理。只有终端操作
iterator()
spliterator()
不是

因此,短路并行流不会处理所有元素,但当其他工作线程仍在处理过时的元素时,返回已计算的结果可能需要更长的时间

如果希望提前返回,接受可能仍在运行的后台线程,则流API
IntStream.range(0, 2000).parallel()
    .map(i -> { LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(50)); return i;})
    .filter(i->i%397==396)
    .findAny();
private int work(int i) throws InterruptedException {
    System.out.println( "working... " + i );
    Thread.sleep(i * 1000);
    System.out.println( "worked. " + i );
    return i;
}
public void parallel() throws Exception {
    System.out.println( "parallel start." );
    List<Callable<Integer>> jobs = IntStream.range(0, 100)
      .collect(ArrayList::new, (l,i) -> l.add(() -> work(i)), List::addAll);
    ExecutorService pool = Executors.newFixedThreadPool(10);
    Integer result = pool.invokeAny(jobs);
    pool.shutdown();
    System.out.println( "parallel done, result="+result );
}