最近在看java8新特性时看到了stream,其中看到了stream支持串行与并行两种操作,本着实事求是的精神cosmo在实现环境验证了这两种操作的实际效率。
测试代码逻辑是对集合中的元素取筛选对2取余为0的元素。
//串行操作
public static void main(String[] args) {
List<Integer> l = new ArrayList();
for (int i = 0, size = 1000 * 1000 * 1; i < size; i++) {
l.add(i);
}
long begin = System.currentTimeMillis();
List<Integer> collect = l.stream().filter(i -> i % 2 == 0).collect(Collectors.toList());
long end = System.currentTimeMillis();
System.out.println("耗时总计" + (end - begin) + "ms");
}
//并行操作
public static void main(String[] args) {
List<Integer> l = new ArrayList();
for (int i = 0, size = 1000 * 1000 * 1; i < size; i++) {
l.add(i);
}
long begin = System.currentTimeMillis();
List<Integer> collect = l.stream().filter(i -> i % 2 == 0).parallel().collect(Collectors.toList());
long end = System.currentTimeMillis();
System.out.println("耗时总计" + (end - begin) + "ms");
}
cosmo 分别测试了1Million和10Million(100Million,OOM了就不放出来了)
数据量 | 串行 | 并行 |
---|---|---|
1M | 96ms | 163ms |
10M | 117ms | 178ms |
这么看起来在单次计算量较少的情况下并行操作并没有比串行操作快。cosmo猜测是因为在数据规模较小、单次操作花费较小时,串行操作直接计算,而并行操作需先对数据分片后多线程处理。
为了验证我们的猜测正确,对测试代码稍加改动,在每次执行操作之前让线程休眠1ms。
//串行操作
public static void main(String[] args) {
List<Integer> l = new ArrayList();
for (int i = 0, size = 1000 * 1 * 1; i < size; i++) {
l.add(i);
}
long begin = System.currentTimeMillis();
List<Integer> collect = l.stream().filter(i -> {
try {
TimeUnit.MILLISECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return i % 2 == 0;
}).collect(Collectors.toList());
long end = System.currentTimeMillis();
System.out.println("耗时总计" + (end - begin) + "ms");
}
//并行操作
public static void main(String[] args) {
List<Integer> l = new ArrayList();
for (int i = 0, size = 1000 * 1 * 1; i < size; i++) {
l.add(i);
}
long begin = System.currentTimeMillis();
List<Integer> collect = l.stream().filter(i -> {
try {
TimeUnit.MILLISECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return i % 2 == 0;
}).parallel().collect(Collectors.toList());
long end = System.currentTimeMillis();
System.out.println("耗时总计" + (end - begin) + "ms");
}
数据量 | 串行 | 并行 |
---|---|---|
1000 | 1089ms | 308ms |
10000 | 10068ms | 2577ms |
不出所料在增加单次计算的花费之后并行操作效率远高于串行操作。由此可见并行操作并非一定比串行操作快,我们在使用时一定要注意应用场景。