我正在尝试将 ArrayList 转换为树状图,所以我编写了一种基准来比较各种方法:
1) 在并行流中映射
2) 在流中映射
3) 对于每个在流中
4) 对于每个在并行流中
5) for 循环
如果 ArrayList 大小很小(比如 10,000),一切正常,但是当大小很大时,比如说一百万,即使在 9 分钟后它仍然运行"forEach Parallel Stream"方法。我用尝试捕捉包围了它,但它很干净。
我知道创建新线程会有一些开销,但是 parallelStream 使用 threadPool,所以它应该很低,对吧?
public class Set {
private String foo;
private int bar;
public Set(String foo, int bar) {
this.foo = foo;
this.bar = bar;
}
public String getFoo() {
return foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
public int getBar() {
return bar;
}
public void setBar(int bar) {
this.bar = bar;
}
}
主要
public class Test {
TreeMap tr=new TreeMap();
public static void main(String[] args) {
Test t = new Test();
t.g();
}
public void g(){
ArrayList<Set> ar=new ArrayList<>();
for (int i = 0; i < 1_000_000; i++) {
ar.add(new Set(UUID.randomUUID().toString(), new Random().nextInt()));
}
long start;
long end;
System.out.println("Parallel toMap");
start=System.nanoTime();
tr.putAll(ar.parallelStream().collect(Collectors.toMap(Set::getFoo, Set::getBar)));
end=System.nanoTime();
System.out.println(end-start);
tr=new TreeMap();
System.out.println("non-Parallel toMap");
start=System.nanoTime();
tr.putAll(ar.stream().collect(Collectors.toMap(Set::getFoo, Set::getBar)));
end=System.nanoTime();
System.out.println(end-start);
tr=new TreeMap();
System.out.println("non-Parallel forEach");
start=System.nanoTime();
ar.stream().forEach(product -> {
tr.put(product.getFoo(), product.getBar());
});
end=System.nanoTime();
System.out.println(end-start);
tr=new TreeMap();
System.out.println("Parallel forEach");
start=System.nanoTime();
//HANGS SOMEWHERE HERE
ar.parallelStream().forEach(product -> {
try {
tr.put(product.getFoo(), product.getBar());
} catch (Exception e) {
System.out.println(e.getLocalizedMessage());
}
});
end=System.nanoTime();
System.out.println(end-start);
tr=new TreeMap();
System.out.println("non-Parallel loop");
start=System.nanoTime();
for(Set product:ar)
tr.put(product.getFoo(), product.getBar());
end=System.nanoTime();
System.out.println(end-start);
}
}
大小 10_000 的输出如下所示
Parallel toMap
130793206
non-Parallel toMap
21729202
non-Parallel forEach
7601349
Parallel forEach
3233395
non-Parallel loop
9744039
"for 循环"是预期的最慢
正如预期的那样,"paralled forEach"比"non-parallel forEach"更快
"并行到地图"比"非平行到地图"慢5倍??什么?英特尔睿频加速在起作用?
回到为什么当数组列表很大时,"并行蒸汽中的 forEach "会失败?
运行 i7 2670QM,因此线程池大小应为 8
TreeMap
不是线程安全的。因此,当从多个线程使用它时,所有赌注都关闭了。你可以在HashMap
中获得无限循环。据推测,TreeMap
在某种程度上表现得非常糟糕。
(关于基准测试:由于 JVM 的"预热"方式,您应该为每个测试启动一个新过程。还要在一个进程中连续多次运行测试。