Java Stream 和 parallelStream 有什么区别?并行流为什么不一定更快?
下面是一段教学模拟,不是真实面试记录。
🧑💻 面试官:列表处理慢,改成 parallelStream 会更快吗?
🙋♂️ 我:会,多线程同时处理。
🧑💻 面试官:列表只有二十条,每条只做一次加法呢?
🙋♂️ 我:可能调度开销反而更大。
🧑💻 面试官:如果每条任务都写同一个 ArrayList,或者等待外部接口呢?“能并行”与“值得并行”分别怎么判断?
并行流多了「拆分和合并」,不只是给原代码增加线程。先确认工作可拆、共享状态安全,再评测有没有净收益。
面试速答(60 秒版)
Stream 描述一条数据处理流水线,中间操作通常是惰性的,遇到终止操作才执行。parallelStream 则允许把数据拆成多个部分,并行处理后合并结果。
并行不一定更快,因为拆分、调度和合并都有成本。数据少、单项工作轻,或者任务依赖顺序时,收益可能被开销抵消。
另外,处理函数需要避免干扰数据源和不安全的共享写入,归约规则也要满足并行组合所需的条件。
实际选型中,我会先确认正确性,再在真实数据规模和服务并发下测试。阻塞 I/O 或需要严格并发限额的任务,不能只靠 parallelStream 来管理。

知识点详解:流水线执行,和流水线并行是两件事
Stream 不会一写 map 就立即处理所有数据
假设一条流水线是筛选记录、转换字段,再收集结果。
筛选和转换属于中间操作,通常等到收集等终止操作出现,才真正推动处理。Stream 也不是复制出来的一份集合,不应该用完后继续反复消费同一条流。
因此,分析耗时要看最终执行过程,而不是在创建流水线前后简单计时。Stream API 说明
并行需要拆得开,也合得回来
假设处理一百万个独立数值,每项都要进行较多计算。数据能合理拆分,结果也可以合并,这种任务可能适合评估并行。
但二十个元素每项只做简单映射,总工作很少,调度与合并就可能占主要时间。
归约也需要正确规则。减法等不满足结合性的操作,拆分后组合顺序变化,可能得到不同结果。浮点加法还涉及数值误差,不能因为数学上看起来是求和,就保证位级结果完全一致。
把结果写进同一个列表,会发生什么?
假设多个并行任务在 forEach 中调用同一个普通 ArrayList 的 add。它不是为并发修改设计的,可能出现数据问题。
给列表加锁可能避免部分竞争,但又会引入串行等待,未必带来更快处理。通常应优先采用适合流水线的收集与归约方式,明确每个阶段的状态归属。
同样,修改正在遍历的数据源,也可能干扰流处理。并行要求我们重新审视副作用,不是保留原代码所有共享写入,再换一个方法名。Oracle 并行流说明

阻塞 I/O 不等于适合自动并行
如果每项都请求远程服务,速度取决于网络、下游容量和并发限制。增加并行可能让下游过载,或把其他工作一起拖慢。
常见 OpenJDK 实现中的并行流通常涉及 ForkJoin 公共池。不要把它理解成每个请求都有一套完全独立、可以随便阻塞的线程池;具体执行环境还要按实现核对。
需要限制同时请求数量、控制超时和取消时,显式任务执行器或异步请求管理往往更容易表达规则。
本文讲的是 Java 专属 Stream 机制,不提供伪造的 TypeScript 或 Python 同名 API。其他语言有各自并行方案,性能与生命周期需要独立讨论。
面试官继续追问
并行流的 forEach 会保持原顺序吗?
不要默认保持。若要求 encounter order,应检查对应操作,如 forEachOrdered,但保持顺序也会影响并行处理的取舍。
单机测试更快,就能直接在接口里用吗?
还需要考虑多个请求同时竞争线程与 CPU。单次任务加速,不代表服务总吞吐和尾延迟变好。
怎样选择测试数据?
覆盖实际大小、每项计算量和真实分布,进行预热、重复测量,并检查结果正确性。不要仅凭一次毫秒打印得出普遍结论。
面试速记卡
- Stream:惰性的处理流水线,终止操作推动执行。
- parallelStream:拆分、并行执行、合并结果。
- 正确性:避免数据源干扰、不安全共享写入和错误归约。
- 性能:工作量要覆盖拆分、调度和合并成本。
- 选型:真实并发下评测;阻塞 I/O 与限流不能只交给并行流。
公司面试真题
真题根据求职者公开面经整理,题意经过概括,非逐字原话或公司官方题库;本文为 Sunday 的独立解析。
京东 · Java后台 · 校招
JDK 8 的 Stream 管道怎样工作?(题意整理)
京东 Java 后台三面凉经 ↗
原帖编辑于 2019-08-23(历史校招面经)