如何让Java Parallel Stream不将主线程作为工作线程?
Java并行流是否会使用主线程?如何排除主线程参与处理?
问题核心解答
是的,Java并行流默认会让发起流操作的主线程参与任务处理。这是因为并行流底层依赖ForkJoinPool的工作窃取机制:主线程提交并行流任务后,不会完全闲置等待,而是会主动执行一部分任务,和池中的工作线程一起完成计算,以此提升整体效率。
从你提供的示例输出也能明确看到,主线程main确实在处理元素3,和ForkJoinPool.commonPool-worker-1/2共同完成了并行流的处理工作。
如何排除主线程参与处理?
要让主线程只负责提交任务、不参与实际的流元素处理,你需要自定义独立的ForkJoinPool,并将并行流操作提交到这个自定义池中执行。这样并行流的所有任务都会由自定义池中的工作线程处理,主线程不会介入。
修改后的示例代码如下:
package org.example; import java.util.Arrays; import java.util.concurrent.ExecutionException; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.atomic.AtomicInteger; public class StreamBasic { private AtomicInteger atomicInteger = new AtomicInteger(0); public static void main(String[] args) { StreamBasic streamBasic = new StreamBasic(); streamBasic.test(); } private void test() { int[] nums = {1, 2, 3}; System.out.println("start" + "-" + Thread.currentThread().getName()); // 自定义ForkJoinPool,指定工作线程数量 ForkJoinPool customPool = new ForkJoinPool(2); try { // 将并行流操作提交到自定义池执行 customPool.submit(() -> Arrays.stream(nums) .parallel() .map(n -> { try { for (int i=0;i<2;i++) { Thread.sleep(100); System.out.println(n + "-" + Thread.currentThread().getName()); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } n *= 2; atomicInteger.incrementAndGet(); return n; }) .toArray() ).get(); // 阻塞等待任务执行完成 } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } finally { customPool.shutdown(); // 关闭自定义池,释放资源 } System.out.println("end" + "-" + Thread.currentThread().getName()); } }
效果说明
运行修改后的代码,输出会显示所有元素都由自定义池中的工作线程(比如ForkJoinPool-1-worker-1、ForkJoinPool-1-worker-2)处理,主线程main只会打印start-main和end-main,不会参与任何元素的计算逻辑。
另外需要注意:自定义ForkJoinPool是独立于全局默认的commonPool的,这样可以避免你的并行流任务和其他系统任务争抢资源,也能更精准地控制线程数量。
内容的提问来源于stack exchange,提问作者Jeff Xu
相关产品推荐
相关产品推荐

