游乐游手机版
首页/编程语言/文章详情

怎么区分 Stream 流的并行处理 parallel() 与普通处理在底层线程池(ForkJoinPool)的共用

时间:2026-04-29 14:19
怎么区分 Stream 流的并行处理 parallel() 与普通处理在底层线程池(ForkJoinPool)的共用 简单来说,并行流的 parallel() 并不创建新线程池,而是直接复用 JVM 全局共享的 ForkJoinPool commonPool()。普通流(stream())则完全是另

怎么区分 Stream 流的并行处理 parallel() 与普通处理在底层线程池(ForkJoinPool)的共用

怎么区分 Stream 流的并行处理 parallel() 与普通处理在底层线程池(ForkJoinPool)的共用

简单来说,并行流的 parallel() 并不创建新线程池,而是直接复用 JVM 全局共享的 ForkJoinPool.commonPool()。普通流(stream())则完全是另一回事——它只在当前调用线程中顺序执行,根本不涉及任何线程池和并发调度。

parallel() 的线程池来源是固定的

所有未显式指定线程池的并行流,底层都走同一个 ForkJoinPool 实例:ForkJoinPool.commonPool()。这里有个关键点:这个池子不是每次调用时新建的,而是 JVM 启动时初始化一次的静态共享池。

  • 它的默认并行度计算公式是:Runtime.getRuntime().a vailableProcessors() - 1。举个例子,在一台8核的机器上,默认就是7个并行线程。
  • 这个默认值是可以提前配置的,通过系统属性就能调整:System.setProperty("ja va.util.concurrent.ForkJoinPool.common.parallelism", "12");
  • 需要注意的是,这个设置是全局性的。它影响的不仅仅是 parallelStream,所有使用 commonPool 的地方都会生效,比如 ForkJoinTask.invoke()CompletableFuture 的默认异步执行。

普通流 stream() 完全不依赖线程池

list.stream().filter(...).map(...) 这样的普通流操作,整个链路都在当前线程内完成。没有任务提交、没有工作窃取、也没有线程调度的开销。它的执行模型和传统的 for 循环一样,是纯同步、单线程且行为可预测的。

  • 它不会触发任何 ForkJoinPool 的初始化。
  • 不会占用 commonPool 的线程或队列资源。
  • 即使在多线程环境中调用,每个线程也只是各自执行自己的 stream 操作,彼此完全隔离。

如何验证是否共用同一个 commonPool

想亲眼看看是不是真的共用一个池子?可以通过打印线程名或检查池状态来验证:

  • 在 parallelStream 操作中打印线程名:
    .forEach(x -> System.out.println(Thread.currentThread().getName()))
    你会看到输出中包含类似 ForkJoinPool.commonPool-worker-1 这样的名称。
  • 对比调用 ForkJoinPool.commonPool().toString()list.parallelStream().count() 前后,池子的 activeThreadCount 或 poolSize 等状态值会发生变化。
  • 最直接的证据是,当多个并行流同时运行时,它们的子任务会竞争同一组 worker 线程,而不是各自独占一套资源。

注意:sequential() 不会切换线程池

这里有个容易混淆的地方:调用 .parallel().sequential() 只是让后续操作退回到单线程顺序执行模式。但是,整个流可能已经在 commonPool 中启动过 fork/join 分支了。这个方法并不会释放线程,也不会切换到其他池子——它的作用仅仅是“不再进行并行调度”,而实际执行任务的线程,很可能还是 commonPool 里的某个 worker。

来源:https://www.php.cn/faq/2387677.html
上一篇如何在 Java 中使用 LinkedBlockingQueue 在生产者消费者模型中实现流量的削峰平谷 下一篇怎么利用 Unsafe 类的 staticFieldBase 实现对类静态变量在元空间内存地址的直接访问
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
CentOS与Golang打包常见兼容性问题探讨
编程语言 · 2026-07-01

CentOS与Golang打包常见兼容性问题探讨

CentOS与Golang打包的兼容性问题集中在glibc版本不匹配、交叉编译环境变量错误、依赖库缺失及Go依赖管理不规范。可通过Docker容器编译、选择兼容Go版本、正确设置GOOS GOARCH环境变量、安装对应开发包及使用GoModules解决。

CentOS中Fortran与Python如何协同工作从入门到实战完整教程
编程语言 · 2026-07-01

CentOS中Fortran与Python如何协同工作从入门到实战完整教程

在CentOS中,Fortran与Python可通过f2py、SWIG、共享库调用或subprocess协同。f2py封装Fortran为Python模块,支持数组运算;共享库需手动对齐数据类型;系统调用适合独立计算。

CentOS中Golang打包优化方法
编程语言 · 2026-07-01

CentOS中Golang打包优化方法

在CentOS中优化Golang编译打包,可显著提升编译速度并减小二进制文件体积。关键技巧包括:设置环境变量、使用Go模块管理依赖、编译时添加-ldflags= "-s-w "去除调试信息、利用UPX工具压缩、运行strip清理符号表,以及优化cgo内C代码的编译选项。综合运用这些方法能有效优化最终程序。

在CentOS系统中cpustat与其他工具协同使用的完整方法
编程语言 · 2026-07-01

在CentOS系统中cpustat与其他工具协同使用的完整方法

cpustat作为sysstat包的CPU监控工具,可通过管道与grep等命令配合过滤数据,利用脚本自动记录带时间戳的日志,或结合图形工具查看,也可格式化输出后接入Zabbix、Grafana等Web监控系统,实现可视化与告警。

CentOS中readdir与其他Linux发行版的差异
编程语言 · 2026-07-01

CentOS中readdir与其他Linux发行版的差异

CentOS基于RHEL,与Ubuntu、Debian、Fedora在包管理器(yum dnfvsapt)、默认文件系统(XFSvsext4)等存在差异,但readdir等系统调用遵循POSIX标准,行为一致。