-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathCourse6Performance.java
66 lines (63 loc) · 2.94 KB
/
Course6Performance.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package com.java8.lambda.chapter6;
import java.util.List;
/**
* 性能
*
* 影响并行流性能的主要因素有 5 个,依次分析如下:
*
* (一)数据大小
* 输入数据的大小会影响并行化处理对性能的提升。将问题分解之后并行化处理,再将结果合并会带来额外的开销。
* 因此只有数据足够大、每个数据处理管道花费的时间足够多时,并行化处理才有意义。
*
* (二)源数据结构
* 每个管道的操作都基于一些初始数据源,通常是集合。
* 将不同的数据源分割相对容易,这里的开销影响了在管道中并行处理数据时到底能带来多少性能上的提升。
*
* (三)装箱
* 处理基本类型比处理装箱类型要快。
*
* (四)核的数量
* 极端情况下,只有一个核,因此完全没必要并行化。
* 显然,拥有的核越多,获得潜在性能提升的幅度就越大。
*
* (五)单元处理开销
* 比如数据大小,这是一场并行执行花费时间和分解合并操作开销之间的战争。
* 花在流中每个元素身上的时间越长,并行操作带来的性能提升越明显。
*
*
*
* 在底层,并行流还是沿用了 fork/join 框架。
* fork 递归式地分解问题,然后每段并行执行,最终由 join 合并结果,返回最后的值。
*
* 直观上看,能重复将数据结构对半分解的难易程度,决定了分解操作的快慢。能对半分解同时意味着待分解的值能够被等量地分解。
*
* 我们可以根据性能的好坏,将核心类库提供的通用数据结构分成以下 3 组。
* (1)性能好
* ArrayList 、数组或 IntStream.range ,这些数据结构支持随机读取,也就是说它们能轻而易举地被任意分解。
* (2)性能一般
* HashSet 、 TreeSet ,这些数据结构不易公平地被分解,但是大多数时候分解是可能的。
* (3)性能差
* 有些数据结构难于分解,比如,可能要花 O(N) 的时间复杂度来分解问题。
* 其中包括 LinkedList ,对半分解太难了。还有 Streams.iterate 和 BufferedReader.lines ,它们长度未知,因此很难预测该在哪里分解。
*
*
* 在讨论流中单独操作每一块的种类时,可以分成两种不同的操作:无状态的和有状态的。
* 无状态操作整个过程中不必维护状态,有状态操作则有维护状态所需的开销和限制。
* 如果能避开有状态,选用无状态操作,就能获得更好的并行性能。
* 无状态操作包括 map 、filter 和 flatMap ,有状态操作包括 sorted 、 distinct 和 limit 。
*
*
* @author hzweiyongqiang
*/
public class Course6Performance {
/**
* 并行求和
* @param values
* @return
*/
public int addIntegers(List<Integer> values) {
return values.parallelStream()
.mapToInt(i->i)
.sum();
}
}