串行流和并行流适用场景不同:串行流单线程顺序执行,适合调试和顺序敏感操作;并行流基于forkjoinpool多线程处理,仅cpu密集型大任务(>10,000数据)才可能提速,需规避i/o、锁竞争与线程安全问题。

串行流和并行流不是“快慢二选一”,而是适用场景不同。用错地方,反而拖慢程序。
执行模型与线程行为
串行流在当前线程中顺序执行,没有线程切换、无同步开销,逻辑清晰可控。并行流基于 ForkJoinPool.commonPool() 启动多个工作线程,默认线程数通常等于 CPU 核心数减一;它会把数据拆成子任务(如数组按索引切分,集合靠 Spliterator 分割),各线程独立处理后再合并结果。
- 串行流:始终单线程,顺序稳定,适合调试和顺序敏感操作
- 并行流:多线程并发,但不保证元素处理顺序(forEach 不保序,需用 forEachOrdered 才能维持顺序,但会牺牲并行性)
- 并行流可显式切换回串行:调用 sequential(),且最后调用的 parallel()/sequential() 决定最终执行模式
性能表现的关键影响因素
并行流不是“自动加速器”。它的收益取决于任务类型、数据规模和系统资源:
- CPU 密集型任务(如数学计算、字符串转换、哈希生成)才真正受益于并行;I/O 操作、锁竞争、对象创建频繁的任务反而更慢
- 数据量门槛明显:一般建议数据量 >10,000 条才考虑并行;低于该量级时,拆分、线程调度、结果合并的开销常超过收益
- 默认 ForkJoinPool 是共享的,若其他模块也大量使用 parallelStream,可能引发线程争抢;可通过 ForkJoinPool.commonPool().getParallelism() 查看当前并行度,或用自定义线程池替代(如 new ForkJoinPool(8))
线程安全与副作用风险
串行流天然规避并发问题;并行流则要求所有中间操作(filter/map/reduce)无共享可变状态。
- 避免在 lambda 中修改外部变量(如 ArrayList.add、static 计数器),否则结果不可预测
- reduce 和 collect 操作是安全的,但需使用正确的组合器(如 Collectors.toList() 内部已线程安全)
- 若必须收集到共享容器,应改用线程安全结构(如 ConcurrentHashMap)或加锁,但这通常抵消并行优势
实际选型建议
别凭感觉切换 parallelStream,先问三个问题:
- 这个操作是否纯计算?有没有数据库调用、文件读写、网络请求?——有就别并行
- 集合大小是否稳定超过一万?能否预估最小数据量?——小数据用串行更稳
- 输出顺序是否关键?是否允许结果偶尔乱序?——要严格顺序,优先串行或用 forEachOrdered(慎用)
不复杂但容易忽略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











