Java 并行与串行深入解析:性能优化与实战指南
在高性能应用开发中,我们常常会面临 串行(Serial) 和 并行(Parallel) 的选择。串行执行任务简单直观,但并行能更高效地利用 CPU 资源,提高吞吐量。然而,并行并不总是比串行快,如何合理选择和优化并行任务,才是性能提升的关键。本文将深入解析 Java 并行与串行的原理 ,并结合 实战代码 带你掌握 高效的并行计算 方法。
1. 什么是串行与并行?
(1)串行(Serial)
串行指的是任务按顺序执行 ,一个任务执行完后,才会执行下一个任务。例如,以下代码模拟 读取数据库 → 计算数据 → 写入文件 的串行执行流程:
java
public class SerialProcessing {
public static void main(String[] args) {
long start = System.currentTimeMillis();
readFromDatabase(); // 假设耗时 2s
processData(); // 假设耗时 3s
writeToFile(); // 假设耗时 2s
System.out.println("总耗时: " + (System.currentTimeMillis() - start) + " ms");
}
static void readFromDatabase() { sleep(2000, "读取数据库"); }
static void processData() { sleep(3000, "计算数据"); }
static void writeToFile() { sleep(2000, "写入文件"); }
static void sleep(int millis, String task) {
try {
System.out.println(task + " 开始...");
Thread.sleep(millis);
System.out.println(task + " 结束");
} catch (InterruptedException e) {}
}
}
执行结果:
读取数据库 开始...
读取数据库 结束
计算数据 开始...
计算数据 结束
写入文件 开始...
写入文件 结束
总耗时: 7000 ms
🚨 问题 :任务串行执行 ,总耗时 = 2s + 3s + 2s = 7s,如果任务更多,系统响应会非常慢。
(2)并行(Parallel)
并行执行任务意味着 多个任务同时运行 ,在多核 CPU 环境下能够显著提高效率。例如,我们可以使用 多线程并行执行任务:
java
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ParallelProcessing {
public static void main(String[] args) throws InterruptedException {
long start = System.currentTimeMillis();
ExecutorService executor = Executors.newFixedThreadPool(3);
executor.execute(() -> sleep(2000, "读取数据库"));
executor.execute(() -> sleep(3000, "计算数据"));
executor.execute(() -> sleep(2000, "写入文件"));
executor.shutdown();
while (!executor.isTerminated()) { Thread.sleep(100); }
System.out.println("总耗时: " + (System.currentTimeMillis() - start) + " ms");
}
static void sleep(int millis, String task) {
try {
System.out.println(task + " 开始...");
Thread.sleep(millis);
System.out.println(task + " 结束");
} catch (InterruptedException e) {}
}
}
执行结果(并行执行,可能不同):
读取数据库 开始...
计算数据 开始...
写入文件 开始...
读取数据库 结束
写入文件 结束
计算数据 结束
总耗时: 3000 ms
✅ 并行执行,耗时大幅减少!
🚀 比串行执行快了 7s → 3s
,大幅优化了执行时间。
2. 并行 vs. 串行:如何选择?
对比项 | 串行(Serial) | 并行(Parallel) |
---|---|---|
执行方式 | 任务逐个执行 | 任务同时执行 |
CPU 利用率 | 低 | 高 |
吞吐量 | 低 | 高 |
适用场景 | 任务依赖强,逻辑顺序不可分 | 任务独立,计算密集型 |
资源消耗 | 低(一个线程) | 高(多线程) |
调试难度 | 简单 | 复杂(需考虑同步、锁) |
🚀 适合使用并行的场景 :
✅ 计算密集型任务 (如大数据计算、AI 训练)
✅ I/O 密集型任务 (如多个 API 调用、批量文件处理)
✅ 任务独立,可拆分成多个子任务
🚨 不适合并行的场景 :
❌ 任务之间强依赖 (如步骤 A 结果决定 B 的输入)
❌ 线程切换开销大,反而影响性能(如小任务并行导致频繁上下文切换)
3. Java 并行实战
(1)使用 ForkJoinPool
并行计算
ForkJoinPool
是 Java 7 引入的 并行计算框架 ,适用于大规模递归任务,如 并行数组求和:
java
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.ForkJoinPool;
class ParallelSum extends RecursiveTask<Long> {
private static final int THRESHOLD = 10000;
private long[] array;
private int start, end;
public ParallelSum(long[] array, int start, int end) {
this.array = array;
this.start = start;
this.end = end;
}
protected Long compute() {
if ((end - start) <= THRESHOLD) {
long sum = 0;
for (int i = start; i < end; i++) sum += array[i];
return sum;
} else {
int mid = (start + end) / 2;
ParallelSum leftTask = new ParallelSum(array, start, mid);
ParallelSum rightTask = new ParallelSum(array, mid, end);
leftTask.fork(); // 异步执行左半部分
return rightTask.compute() + leftTask.join();
}
}
}
public class ForkJoinExample {
public static void main(String[] args) {
long[] array = new long[1000000];
for (int i = 0; i < array.length; i++) array[i] = i;
ForkJoinPool pool = new ForkJoinPool();
long sum = pool.invoke(new ParallelSum(array, 0, array.length));
System.out.println("总和: " + sum);
}
}
✅ 适用于大规模数据计算,充分利用 CPU 并行能力!
(2)使用 parallelStream()
并行处理集合
java
import java.util.List;
import java.util.stream.IntStream;
public class ParallelStreamExample {
public static void main(String[] args) {
List<Integer> numbers = IntStream.rangeClosed(1, 1000000).boxed().toList();
long start = System.currentTimeMillis();
int sum = numbers.parallelStream().mapToInt(Integer::intValue).sum();
System.out.println("总和: " + sum + ", 耗时: " + (System.currentTimeMillis() - start) + " ms");
}
}
✅ 比传统 for
循环更快!
4. 总结
✅ 串行适用于任务依赖强、执行顺序严格的场景 。
✅ 并行适用于 CPU 密集、I/O 密集、可拆分任务 。
✅ 合理选择 ForkJoinPool
或 parallelStream()
提升效率!
并行计算是高性能开发的关键,希望本文能帮助你更高效地编写 Java 并行程序!🚀🚀🚀