默认情况下,parallelStream中commonPool的大小应为cpu_cores - 1
。
但是,在我的应用程序中,它总是大于硬件cpu_cores
。
VisualVM屏幕截图:
太困惑了,我已经搜索了一半的互联网,但是找不到答案。
我的配置:
Runtime.getRuntime().availableProcessors()=12
java.util.concurrent.ForkJoinPool.common.parallelism=null
(默认设置)
我的代码:
final CountDownLatch countDownLatch = new CountDownLatch(tempList.size());
tempList.parallelStream().forEach(om -> {
countDownLatch.countDown();
redisReBloomService.add(config.getRedisKey(), om.getChannelNo());
});
countDownLatch.await();
此外,我尝试了自定义池设置,但也不起作用-
ForkJoinPool forkJoinPool = new ForkJoinPool(3);
forkJoinPool.submit(() -> {
tempList.parallelStream().forEach(om -> {
countDownLatch.countDown();
redisReBloomService.add(config.getRedisKey(), om.getChannelNo());
}).get();
});
一些信息: https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ForkJoinPool.html Custom thread pool in Java 8 parallel stream
答案 0 :(得分:3)
ForkJoinPool
中的并行度不是池中最大线程数。它是活动线程的目标。如果某些线程被阻塞,则池可能会启动新线程以达到所需的并行度。
来自ForkJoinPool的文档:
即使某些任务因等待加入其他任务而停滞不前,该池也会尝试通过动态添加,暂停或恢复内部工作线程来维护足够的活动(或可用)线程。但是,面对阻塞的I / O或其他不受管理的同步,不能保证这样的调整。嵌套的ForkJoinPool.ManagedBlocker接口可扩展所容纳的同步类型。
该屏幕快照显示,当其他线程切换到状态Monitor
(粉红色的)时,新线程恰好在同一时间启动。我的猜测是,redisReBloomService.add(…)
调用必须在该监视器上等待时在内部使用ManagedBlocker
,从而导致池启动更多的工作线程。
这是一个使用ManagedBlocker
的小例子,它演示了您观察到的类似行为。 ManagedBlocker
睡眠1秒后,通常可以在VisualVM中观察到新的辅助线程。
public class ForkJoinPoolTest {
@Test
public void testManagedBlocker() throws InterruptedException {
// wait to be able to connect with VisualVM
Thread.sleep(10_000);
IntStream.range(0, 100).parallel().peek(number -> {
doWork();
// Run a managed blocker some times.
// Every time it blocks, a new worker thread might be started.
if (ThreadLocalRandom.current().nextInt(10) == 0) {
try {
ForkJoinPool.managedBlock(new ManagedBlocker() {
@Override
public boolean block() throws InterruptedException {
Thread.sleep(1_000);
return true;
}
@Override
public boolean isReleasable() {
return false;
}
});
} catch (InterruptedException ignored) { }
}
})
.sum();
}
/** Some CPU bound workload **/
void doWork() {
for (int i = 0; i < 1_000_000; i++) {
Math.random();
}
}
}