我只是在评估,哪些代码片段在 Java 8 中表现更好。
Snippet 1(在主线程中处理):
public long doSequence() {
DoubleStream ds = IntStream.range(0, 100000).asDoubleStream();
long startTime = System.currentTimeMillis();
final AtomicLong al = new AtomicLong();
ds.forEach((num) -> {
long n1 = new Double (Math.pow(num, 3)).longValue();
long n2 = new Double (Math.pow(num, 2)).longValue();
al.addAndGet(n1 + n2);
});
System.out.println("Sequence");
System.out.println(al.get());
long endTime = System.currentTimeMillis();
return (endTime - startTime);
}
片段 2(在并行线程中处理):
public long doParallel() {
long startTime = System.currentTimeMillis();
final AtomicLong al = new AtomicLong();
DoubleStream ds = IntStream.range(0, 100000).asDoubleStream();
ds.parallel().forEach((num) -> {
long n1 = new Double (Math.pow(num, 3)).longValue();
long n2 = new Double (Math.pow(num, 2)).longValue();
al.addAndGet(n1 + n2);
});
System.out.println("Parallel");
System.out.println(al.get());
long endTime = System.currentTimeMillis();
return (endTime - startTime);
}
片段 3(在线程池的并行线程中处理):
public long doThreadPoolParallel() throws InterruptedException, ExecutionException {
ForkJoinPool customThreadPool = new ForkJoinPool(4);
DoubleStream ds = IntStream.range(0, 100000).asDoubleStream();
long startTime = System.currentTimeMillis();
final AtomicLong al = new AtomicLong();
customThreadPool.submit(() -> ds.parallel().forEach((num) -> {
long n1 = new Double (Math.pow(num, 3)).longValue();
long n2 = new Double (Math.pow(num, 2)).longValue();
al.addAndGet(n1 + n2);
})).get();
System.out.println("Thread Pool");
System.out.println(al.get());
long endTime = System.currentTimeMillis();
return (endTime - startTime);
}
输出在这里:
Parallel
6553089257123798384
34 <--34 milli seconds
Thread Pool
6553089257123798384
23 <--23 milli seconds
Sequence
6553089257123798384
12 <--12 milli seconds!
我期望的是
1) 使用线程池处理的时间应该是最短的,但事实并非如此。(注意我没有包括线程池创建时间,所以它应该很快)
2) 没想到顺序运行的代码是最快的,应该是什么原因。
我使用的是四核处理器。
感谢任何帮助解释上述歧义的人!
最佳答案
您的比较并不完美,肯定是因为缺少 VM 预热。当我简单地重复执行时,我得到不同的结果:
System.out.println(doParallel());
System.out.println(doThreadPoolParallel());
System.out.println(doSequence());
System.out.println("-------");
System.out.println(doParallel());
System.out.println(doThreadPoolParallel());
System.out.println(doSequence());
System.out.println("-------");
System.out.println(doParallel());
System.out.println(doThreadPoolParallel());
System.out.println(doSequence());
结果:
Parallel
6553089257123798384
65
Thread Pool
6553089257123798384
13
Sequence
6553089257123798384
14
-------
Parallel
6553089257123798384
9
Thread Pool
6553089257123798384
4
Sequence
6553089257123798384
8
-------
Parallel
6553089257123798384
8
Thread Pool
6553089257123798384
3
Sequence
6553089257123798384
8
正如@Erwin 在评论中所指出的,请查看 this question 上的答案(在本例中为规则 1)有关如何正确执行此基准测试的想法。
并行流的默认并行性不一定与 fork 连接池提供的并行性相同,线程数与计算机上的内核一样多,尽管当我从你的切换时结果之间的差异仍然可以忽略不计自定义池到通用分支加入池。
关于java - 并行流处理 vs 线程池处理 vs 顺序处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50167559/