在 Java 8 及以上版本中,集合框架提供的 Stream API 让数据处理变得简洁。当数据量很大时,调用 parallelStream 或使用 parallel 方法可以把顺序流切换为并行流,底层基于 ForkJoinPool 将任务拆分成多个子任务,分配到不同 CPU 核心上执行,从而加速计算。
如何开启 ParallelStream
最简单的方式是直接调用集合的 parallelStream 方法,也可以从已有的顺序流通过 parallel 转换。下面给出基础示例:
import java.util.List;
import java.util.stream.IntStream;
public class ParallelDemo {
public static void main(String[] args) {
// 直接通过集合开启并行流
List<Integer> data = IntStream.range(0, 1000000)
.boxed()
.toList();
long sum = data.parallelStream()
.mapToLong(Integer::longValue)
.sum();
System.out.println(sum);
// 从顺序流转换为并行流
long other = IntStream.range(0, 1000000)
.sequential()
.parallel()
.sum();
System.out.println(other);
}
}
底层运行机制
ParallelStream 默认使用公共的 ForkJoinPool.commonPool,其中的线程数通常等于 CPU 核心数减一。任务会被递归拆分为小块,每个线程处理一部分,最后合并结果。
| 项目 | 说明 |
|---|---|
| 线程池 | ForkJoinPool.commonPool |
| 默认并行度 | Runtime.getRuntime().availableProcessors() - 1 |
| 适用操作 | 无状态、独立元素的聚合计算 |
自定义并行度
若想隔离业务线程,可自建 ForkJoinPool 并提交任务:
import java.util.concurrent.ForkJoinPool;
import java.util.List;
public class CustomPool {
public static void run(List<Integer> list) {
ForkJoinPool pool = new ForkJoinPool(4);
try {
long r = pool.submit(() ->
list.parallelStream().mapToLong(v -> v * 2).sum()
).get();
System.out.println(r);
} catch (Exception e) {
e.printStackTrace();
} finally {
pool.shutdown();
}
}
}
常见陷阱与注意点
- 避免在并行流中修改共享变量,例如使用非线程安全的 ArrayList 做收集。
- 数据量过小时,拆分与合并的开销可能大于计算收益,反而更慢。
- 若操作本身有顺序依赖,如使用 findFirst 之外的有状态中间操作,需谨慎。
- 公共池被阻塞会影响其他并行任务,耗时 IO 不应放进并行流。
适用场景示例
对于 CPU 密集且元素独立的任务,例如批量数值转换、过滤统计,ParallelStream 非常合适。下面示例统计大列表中偶数的个数:
import java.util.List;
import java.util.stream.IntStream;
public class CountEven {
public static void main(String[] args) {
List<Integer> nums = IntStream.range(0, 5000000).boxed().toList();
long even = nums.parallelStream()
.filter(n -> n % 2 == 0)
.count();
System.out.println(even);
}
}
小结
利用 ParallelStream 开启并行流是发挥多核 CPU 能力的便捷手段。只要数据规模足够、操作无共享状态依赖,并通过 parallelStream 或 parallel 方法切换,就能有效加速大数据处理。生产环境中应避开公共池阻塞与错误共享,必要时使用自定义 ForkJoinPool 控制资源。
ParallelStream多核CPU大数据处理修改时间:2026-07-26 20:00:30