面试题答案
一键面试1. 顺序流工作原理
顺序流会按照集合中元素的顺序依次对每个元素进行处理。它在单个线程上执行操作,操作依次进行,一个元素处理完后才处理下一个元素。例如:
val list = listOf(1, 2, 3, 4, 5)
val sum = list.stream()
.map { it * 2 }
.filter { it > 5 }
.sum()
在上述代码中,先对每个元素乘以2,再过滤大于5的元素,最后求和,这些操作是按顺序在单个线程上完成的。
2. 并行流工作原理
并行流利用多线程并行处理集合中的元素。它会将集合拆分成多个子任务,由不同的线程分别处理这些子任务,最后将结果合并。例如:
val list = listOf(1, 2, 3, 4, 5)
val sum = list.parallelStream()
.map { it * 2 }
.filter { it > 5 }
.sum()
并行流会把 list
分成多个部分,不同部分在不同线程上执行 map
和 filter
操作,最后汇总结果求和。
3. 适用场景
- 顺序流适用场景:
- 数据量较小:因为创建和管理多线程有额外开销,在数据量小的情况下,顺序流可能更高效。
- 存在依赖关系:如果操作之间存在依赖关系,例如某个操作的结果依赖于前一个元素操作的结果,顺序流更合适,因为并行流可能打乱元素处理顺序。
- 并行流适用场景:
- 数据量较大:可以充分利用多核CPU的优势,提高处理速度。
- 操作相互独立:例如简单的数值计算、过滤等操作,各元素处理之间没有依赖关系。
4. 在处理大量用户数据计算任务中的选择
- 判断依据:
- 如果计算任务是CPU密集型,例如对每个用户数据进行复杂的数学运算,且数据量很大,并行流可能更合适,因为可以利用多核CPU并行处理。
- 如果计算任务涉及I/O操作,如从数据库读取用户数据或写入结果到文件,并行流不一定能提高性能,因为I/O操作通常是瓶颈,过多线程可能导致线程上下文切换开销增加。
- 如果数据处理存在依赖关系,如计算用户的累积积分,需要根据前面用户的积分计算结果,顺序流更合适。
- 优化思路:
- 并行流:
- 合理设置并行度:通过
parallelStream().parallelism(n)
方法设置并行线程数,根据CPU核心数和任务特点调整,避免线程过多导致上下文切换开销过大。 - 减少数据共享:并行流中尽量避免共享可变状态,否则需要额外同步机制,降低并行效率。
- 合理设置并行度:通过
- 顺序流:
- 如果数据量较大且操作简单,可考虑先进行分块处理,再合并结果,模拟并行效果。
- 优化单个元素处理逻辑,减少每个元素处理时间。
- 并行流: