本文目录导读:

没错,并行流(Parallel Stream) 确实是 Java 8 引入的一项强大特性,其核心目的就是利用多核处理器的计算能力,将数据拆分后交给多个线程并行处理,从而加速数据处理。
它是对 Fork/Join 框架的一种上层封装,使得开发者无需手动管理复杂的线程池和任务拆分,只需调用一个方法 (parallelStream() 或 .parallel()) 就能实现数据集的并行处理。
并行流的工作原理 (关键)
- 拆分 (Split): 数据源 (通常是集合,如 List, Set) 会被递归地拆分成更小的子集,这是通过
Spliterator(可分割迭代器) 完成的。 - 执行 (Compute): 拆分后的子集会被分配到由
ForkJoinPool(Fork/Join 线程池) 管理的多个工作线程上并行执行,默认情况下,线程池的大小等于Runtime.getRuntime().availableProcessors(),即你计算机的 CPU 核心数。 - 合并 (Combine): 所有子集的处理结果会被合并成一个最终的结果。
何时使用并行流? (适合的场景)
并行流并非万能灵药,只有特定场景下才能发挥最大效用:
- 数据量大: 数据量必须足够大,以抵消并行化本身带来的开销(线程创建、上下文切换、拆分与合并成本)。
- 计算密集型任务: 每个元素的处理需要消耗大量 CPU 时间,例如复杂的数学计算、图像处理、数据过滤与聚合等。
- 元素之间无状态、无干扰: 处理每个元素的操作必须是独立的,不依赖于其他元素或外部共享的可变状态,这是保证线程安全和正确性的前提。
- 使用合适的
Spliterator: 数据源应该能被高效地拆分,例如基于数组、ArrayList、IntStream.range等,而基于链表 (如LinkedList) 或 文件 I/O 的数据源拆分成本很高。
直观例子 (性能对比)
假设我们要计算 1 到 10_000_000 之间所有质数的个数。
import java.util.stream.IntStream;
import java.util.stream.LongStream;
public class ParallelStreamExample {
public static void main(String[] args) {
long limit = 40_000_000L; // 四千万
// 1. 顺序流 (单线程)
long startSequential = System.nanoTime();
long sequentialCount = LongStream.rangeClosed(2, limit)
.filter(ParallelStreamExample::isPrime)
.count();
long endSequential = System.nanoTime();
System.out.println("顺序流结果: " + sequentialCount +
", 耗时: " + (endSequential - startSequential) / 1_000_000 + " ms");
// 2. 并行流 (多线程)
long startParallel = System.nanoTime();
long parallelCount = LongStream.rangeClosed(2, limit)
.parallel() // 关键一: 切换为并行
.filter(ParallelStreamExample::isPrime)
.count();
long endParallel = System.nanoTime();
System.out.println("并行流结果: " + parallelCount +
", 耗时: " + (endParallel - startParallel) / 1_000_000 + " ms");
}
// 一个简单的质数判断方法 (计算密集型)
public static boolean isPrime(long n) {
if (n < 2) return false;
if (n % 2 == 0) return n == 2;
long maxDivisor = (long) Math.sqrt(n);
for (long i = 3; i <= maxDivisor; i += 2) {
if (n % i == 0) return false;
}
return true;
}
}
// (在你的 4核/8核 机器上运行,并行流通常快数倍)
何时不适合或应谨慎使用并行流? (常见陷阱)
- 数据量太小: 并行化的开销 (创建线程、拆分、合并) 可能超过加速收益。
- I/O 密集型或存在阻塞操作: 如果每个元素处理都要等待网络、数据库或磁盘 I/O,线程的利用率会很低,甚至比顺序流更慢(因为大量线程在等待,而 CPU 空闲),这种情况下使用异步编程模式(如
CompletableFuture)更合适。 - 存在共享的可变状态: 这是最危险的情况。
// 危险!这会破坏结果正确性 List<Integer> list = new ArrayList<>(); data.parallelStream() .filter(e -> e.matchesSomeCondition()) .forEach(e -> list.add(e)); // 共享的可变 ArrayList 不是线程安全的! // 正确做法:使用 .collect(Collectors.toList()) - 需要保证顺序的场景: 并行流的处理顺序是不确定的,如果你依赖元素的原始顺序,必须小心使用
forEachOrdered()或collect(),这会增加性能成本。findFirst()在并行流中比findAny()慢得多。 - 默认的 ForkJoinPool 资源争夺: 所有并行流共享同一个
ForkJoinPool.commonPool(),如果在一个 JVM 中同时运行多个并行流,它们会互相争夺线程资源,导致性能下降,可以尝试使用自定义的ForkJoinPool来隔离。
总结与最佳实践
| 特性 | 并行流 |
|---|---|
| 目的 | 利用多核 CPU 加速计算密集型、可分解的大数据集处理 |
| 原理 | Fork/Join 框架 + Spliterator 自动拆分与合并 |
| 优势 | 代码简洁,无需手动管理线程 |
| 风险 | 线程安全问题、性能反而下降、死锁、资源争夺 |
最佳实践口诀:
- 数据量大 + 计算密集 + 无状态操作 → 大胆用并行流。
- 数据量小 + I/O 频繁 + 有状态/阻塞操作 → 老实写顺序流或异步代码。
- 永远不要对共享的可变变量直接进行并行修改。
- 测试!测试!测试! 在不确定的情况下,用真实数据和
System.nanoTime()对比并行流与顺序流的性能,并确保结果正确,并行流不是银弹。
并行流是 Java 提供的一种高级工具,能有效利用多核资源,但必须理解其适用场景和潜在风险,才能安全、高效地使用它。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播