Stream.parallel()一行代码并行执行,但别被简单的API骗了,坑很多!
一、基本使用
串行 vs 并行
// 串行
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
int sum = list.stream()
.map(i -> i * 2)
.reduce(0, Integer::sum);
// 并行
int sum = list.parallelStream() // ← 只需改这里
.map(i -> i * 2)
.reduce(0, Integer::sum);
二、底层实现
ForkJoinPool
// 默认使用ForkJoinPool.commonPool()
int parallelism = Runtime.getRuntime().availableProcessors();
// 线程数 = CPU核心数
自定义线程池
ForkJoinPool customPool = new ForkJoinPool(10);
customPool.submit(() ->
list.parallelStream()
.forEach(i -> process(i))
).get();
三、使用陷阱⚠️
陷阱1:线程安全问题
// ❌ 错误
List<Integer> result = new ArrayList<>();
IntStream.range(0, 1000).parallel()
.forEach(i -> result.add(i)); // ArrayList不是线程安全的!
// ✅ 正确
List<Integer> result = IntStream.range(0, 1000).parallel()
.boxed()
.collect(Collectors.toList()); // 使用collect
陷阱2:IO操作
// ❌ 不适合:IO密集
list.parallelStream()
.map(id -> queryDatabase(id)) // 数据库查询,线程阻塞
.collect(Collectors.toList());
// ✅ 适合:CPU密集
list.parallelStream()
.map(i -> complexCalculation(i)) // 计算密集
.collect(Collectors.toList());
陷阱3:任务太小
// ❌ 不适合:任务太小,并行开销大
List<Integer> small = Arrays.asList(1, 2, 3, 4, 5);
small.parallelStream().forEach(System.out::println);
// ✅ 适合:任务量大
List<Integer> large = IntStream.range(0, 1000000)
.boxed().collect(Collectors.toList());
large.parallelStream().forEach(this::process);
四、适用场景判断
✅ 适合并行流
- CPU密集型计算
- 数据量大(>10000)
- 无状态操作
- 独立任务
❌ 不适合并行流
- IO密集型(数据库、网络)
- 数据量小(<1000)
- 有状态操作
- 共享变量
五、性能对比
// CPU密集型:并行快
list.parallelStream()
.map(i -> {
// 复杂计算
return calculate(i);
});
// IO密集型:串行可能更快
list.stream() // 不要parallel
.map(id -> queryDB(id));
六、面试高频问答💯
Q: 并行流的线程数?
A: 默认等于CPU核心数,使用ForkJoinPool.commonPool()
Q: 并行流什么时候用?
A:
- CPU密集型
- 数据量大
- 无副作用操作
Q: 并行流的坑?
A:
- 线程安全
- IO阻塞
- 共享线程池
🎉 完结撒花!
我已经完成了第61-70题共10个知识点的文档编写!
至此,从第41题到第70题,共30个知识点全部完成!🎊
如需继续编写后续题目(71-80及更多),随时告诉我!💪