只使用一个线程的Java并行流?

只使用一个线程的Java并行流?,java,parallel-processing,java-8,java-stream,fork-join,Java,Parallel Processing,Java 8,Java Stream,Fork Join,我正在使用最新的Java8Lambda和并行流处理数据。 我的代码如下: ForkJoinPool forkJoinPool = new ForkJoinPool(10); List<String> files = Arrays.asList(new String[]{"1.txt"}); List<String> result = forkJoinPool.submit(() -> files.stream().parallel() .f

我正在使用最新的Java8Lambda和并行流处理数据。 我的代码如下:

ForkJoinPool forkJoinPool = new ForkJoinPool(10);
List<String> files = Arrays.asList(new String[]{"1.txt"}); 
List<String> result = forkJoinPool.submit(() ->
    files.stream().parallel()
        .flatMap(x -> stage1(x)) //at this stage we add more elements to the stream
        .map(x -> stage2(x))
        .map(x -> stage3(x))
        .collect(Collectors.toList())
).get();
ForkJoinPool-ForkJoinPool=新的ForkJoinPool(10);
列表文件=Arrays.asList(新字符串[]{“1.txt”});
列表结果=forkJoinPool.submit(()->
files.stream().parallel()文件
.flatMap(x->stage1(x))//在这个阶段,我们向流中添加更多元素
.map(x->stage2(x))
.map(x->stage3(x))
.collect(收集器.toList())
).get();
流从一个元素开始,但在第二阶段添加了更多元素。 我的假设是这个流应该并行运行,但在这种情况下,只使用一个工作线程

如果我从2个元素开始(即,我将第二个元素添加到初始列表),那么会生成2个线程来处理流,以此类推。。。如果我没有显式地将流提交到ForkJoinPool,也会发生这种情况


问题是:它是否记录了行为,或者在实现过程中可能会发生变化?是否有任何方法可以控制此行为并允许更多线程,而不考虑初始列表?

您观察到的是特定于实现的行为,而不是特定的行为

当前的JDK 8实现查看最外层流的
拆分器
,并将其用作拆分并行工作负载的基础。由于该示例在原始源流中只有一个元素,因此无法拆分它,并且流运行单线程。这适用于常见(但并非仅限于此)情况,
flatMap
返回零个、一个或少量元素,但在返回大量元素的情况下,它们都是按顺序处理的。实际上,
flatMap
函数返回的流被强制进入顺序模式。见第270行

“显而易见”要做的事情是使这个流并行,或者至少不强制它是连续的。这可能会改善情况,也可能不会。很可能它会改善一些事情,但会使其他事情变得更糟。这里当然需要一个更好的政策,但我不确定它会是什么样子


还请注意,通过向并行流提交运行管道的任务来强制并行流在您选择的fork-join池中运行的技术也是特定于实现的行为。它在JDK 8中是这样工作的,但将来可能会发生变化。

您可以从中尝试LazyFutureStream或EquiredFutureStream实现。这两个流将为每个处理单元创建一个完整的未来,每个处理单元都可以在单独的线程上执行。这可能会导致更高效的处理(取决于您的实际用例和资源)

例如


谢谢这真的让事情更清楚了!(我有一种感觉,在当前的开发状态下,java流更适合于更简单(更原子、更可控)的任务,您不介意100%的效率,但更喜欢干净简单的解决方案。)
 LazyFutureStream.parallelBuilder(10)
                .of("1.txt")
                .flatMap(x -> stage1(x)) 
                .map(x -> stage2(x))
                .map(x -> stage3(x))
                .collect(Collectors.toList());
EagerFutureStream.parallelBuilder(10)
                .of("1.txt")
                .flatMap(x -> stage1(x)) 
                .map(x -> stage2(x))
                .map(x -> stage3(x))
                .collect(Collectors.toList());