我想使用我的自定义 ForkJoinPool 与 ArrayList.parallelStream() 具有更多的并行性(默认情况下它使用公共池)。
我这样做:
List<String> activities = new ArrayList<>();
for (int i = 0; i < 3000; i++) {
activities.add(String.valueOf(i));
}
ForkJoinPool pool = new ForkJoinPool(10);
pool.submit(() ->
activities.parallelStream()
.map(s -> {
try {
System.out.println("Start task = " + s);
Thread.sleep(100);
System.out.println("End task = " + s);
} catch (InterruptedException e) {
e.printStackTrace();
}
return s;
})
.collect(toList())
).get();
当我观察 VisualVM 的工作原理时,我看到: VisualVM with parallelism 10
在某些时候,一些线程被停放,而其他线程完成其余的工作。当我查看转储时,我看到什么都不做的线程处于停放状态。
实验表明,如果您创建一个带有并行参数的 ForkJoinPool 是 2 的幂,那么一切正常......
List<String> activities = new ArrayList<>();
for (int i = 0; i < 3000; i++) {
activities.add(String.valueOf(i));
}
ForkJoinPool pool = new ForkJoinPool(16);
pool.submit(() ->
activities.parallelStream()
.map(s -> {
try {
System.out.println("Start task = " + s);
Thread.sleep(100);
System.out.println("End task = " + s);
} catch (InterruptedException e) {
e.printStackTrace();
}
return s;
})
.collect(toList())
).get();
它可以是任何小于 64 的 2 的幂(我不知道为什么,但它不超过 ForkJoinPool 的 34 个线程),但如果它不是 2 的幂,我们会得到奇怪的行为。
为什么会发生?如何使用它?