Java ForkJoinPool为什么使用ThreadPerTaskExecutor?
我们在双CPU环境下运行Java中的Akka应用程序,并观察到每次Java ForkJoinPool为什么使用ThreadPerTaskExecutor?,java,concurrency,akka,completable-future,forkjoinpool,Java,Concurrency,Akka,Completable Future,Forkjoinpool,我们在双CPU环境下运行Java中的Akka应用程序,并观察到每次tell都会启动一个新线程,而不是将它们从池中取出。Akka默认调度程序使用ForkJoinPool作为默认执行器。在CompletableFuturecode中,有以下逻辑: private static final boolean useCommonPool = (ForkJoinPool.getCommonPoolParallelism() > 1); private static final Ex
tell
都会启动一个新线程,而不是将它们从池中取出。Akka默认调度程序使用ForkJoinPool
作为默认执行器。在CompletableFuture
code中,有以下逻辑:
private static final boolean useCommonPool =
(ForkJoinPool.getCommonPoolParallelism() > 1);
private static final Executor asyncPool = useCommonPool ?
ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();
static final class ThreadPerTaskExecutor implements Executor {
public void execute(Runnable r) { new Thread(r).start(); }
}
commonPoolParallelism
的值来自Runtime.getRuntime().availableProcessors()-1
(如果未指定JVM属性)-ForkJoinPool.makeCommonPool()
因此,在我们只有两个CPU的情况下,
ForkJoinPool
根本不被使用。默认情况下,它使用ThreadPerTaskExecutor
。我知道我们可以忽略这一点(我们做到了,这会导致性能显著提高)。但这让我想知道为什么会这样?为什么每次启动新线程都比重用池中的一个线程要好,哪怕是一个CPU(不提这两个)?为什么这是ForkJoinPool
的默认行为?如果dispatcher只有一个线程,而该线程被阻塞、死锁等,那么整个actor系统就会突然停止。对于每个任务的线程,这不会发生。感谢您的回答。可以,但如果默认情况下Akka fork join executor具有以下默认属性:parallelism min=8
parallelism factor=3.0
parallelism max=64
。线程池的最小大小是8,所以我假设强制它使用该池是安全的?如果是这样,为什么Akka不将java.util.concurrent.ForkJoinPool.common.parallelism
属性设置为大于1?一个CPU(在我们的例子中是两个)并不意味着调度程序只有一个线程。那么为什么commonPoolParallelism
等于CPU-1呢?