【发布时间】:2020-01-21 12:38:37
【问题描述】:
我尝试使用 Java8(1.8.0_172) stream.parallel() 并行运行 100 个 Sleep 任务,该任务在具有 100 多个可用线程的自定义 ForkJoinPool 中提交。每个任务会休眠 1s。我预计整个工作将在大约 1 秒后完成,因为 100 个睡眠可以并行完成。但是我观察到 7 秒的运行时间。
@Test
public void testParallelStream() throws Exception {
final int REQUESTS = 100;
ForkJoinPool forkJoinPool = null;
try {
// new ForkJoinPool(256): same results for all tried values of REQUESTS
forkJoinPool = new ForkJoinPool(REQUESTS);
forkJoinPool.submit(() -> {
IntStream stream = IntStream.range(0, REQUESTS);
final List<String> result = stream.parallel().mapToObj(i -> {
try {
System.out.println("request " + i);
Thread.sleep(1000);
return Integer.toString(i);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}).collect(Collectors.toList());
// assertThat(result).hasSize(REQUESTS);
}).join();
} finally {
if (forkJoinPool != null) {
forkJoinPool.shutdown();
}
}
}
输出指示在 1 秒的暂停之前执行 ~16 个流元素,然后再执行 ~16 个,依此类推。所以看起来即使 forkjoinpool 是用 100 个线程创建的,也只有大约 16 个线程被使用。
当我使用超过 23 个线程时,这种模式就会出现:
1-23 threads: ~1s
24-35 threads: ~2s
36-48 threads: ~3s
...
System.out.println(Runtime.getRuntime().availableProcessors());
// Output: 4
【问题讨论】:
-
你的
Runtime.getRuntime().availableProcessors()输出是什么? -
availableProcessors() == 4,我添加到描述中
-
顺序执行需要多长时间?
-
这个问题可能观察到同样的事情(没有答案)stackoverflow.com/questions/49068119
-
这种使并行流使用不同线程池的技巧是一种未记录的实现副作用,并且不打算以这种方式工作。所以实现并不关心不同并行的可能性。
标签: java multithreading java-8 java-stream forkjoinpool