经常看到有的框架里用ForkJoinPool.getCommonPoolParallelism(),此次又碰见了,干脆研究一下。
源码:
public class ForkJoinPool extends AbstractExecutorService {
...
static final int commonParallelism;
public static int getCommonPoolParallelism() {
return commonParallelism;
}
...
}
ForkJoinPool.getCommonPoolParallelism()返回的是commonParallelism的值,所以只需要研究在哪里对commonParallelism进行了赋值。源码如下:
...
static final ForkJoinPool common;
static {
...
common = java.security.AccessController.doPrivileged
(new java.security.PrivilegedAction<ForkJoinPool>() {
public ForkJoinPool run() {
return makeCommonPool(); //common的config由此方法返回
}});
int par = common.config & SMASK; // report 1 even if threads disabled
commonParallelism = par > 0 ? par : 1;
}
commonParallelism的值跟par有关, par最终又来源于ForkJoinPool的makeCommonPool()方法,其源码如下:
private static ForkJoinPool makeCommonPool() {
int parallelism = -1;
ForkJoinWorkerThreadFactory factory = null;
UncaughtExceptionHandler handler = null;
try { // ignore exceptions in accessing/parsing properties
String pp = System.getProperty
("java.util.concurrent.ForkJoinPool.common.parallelism");
String fp = System.getProperty
("java.util.concurrent.ForkJoinPool.common.threadFactory");
String hp = System.getProperty
("java.util.concurrent.ForkJoinPool.common.exceptionHandler");
if (pp != null)
parallelism = Integer.parseInt(pp);
if (fp != null)
factory = ((ForkJoinWorkerThreadFactory)ClassLoader.
getSystemClassLoader().loadClass(fp).newInstance());
if (hp != null)
handler = ((UncaughtExceptionHandler)ClassLoader.
getSystemClassLoader().loadClass(hp).newInstance());
} catch (Exception ignore) {
}
if (factory == null) {
if (System.getSecurityManager() == null)
factory = defaultForkJoinWorkerThreadFactory;
else // use security-managed default
factory = new InnocuousForkJoinWorkerThreadFactory();
}
if (parallelism < 0 && // default 1 less than #cores
(parallelism = Runtime.getRuntime().availableProcessors() - 1) <= 0)
parallelism = 1;
if (parallelism > MAX_CAP)
parallelism = MAX_CAP;
return new ForkJoinPool(parallelism, factory, handler, LIFO_QUEUE,
"ForkJoinPool.commonPool-worker-");
}
...
private ForkJoinPool(int parallelism,
ForkJoinWorkerThreadFactory factory,
UncaughtExceptionHandler handler,
int mode,
String workerNamePrefix) {
this.workerNamePrefix = workerNamePrefix;
this.factory = factory;
this.ueh = handler;
this.config = (parallelism & SMASK) | mode;
long np = (long)(-parallelism); // offset ctl counts
this.ctl = ((np << AC_SHIFT) & AC_MASK) | ((np << TC_SHIFT) & TC_MASK);
}
分析makeCommonPool方法可知,其并行度parallelism由jvm启动参数java.util.concurrent.ForkJoinPool.common.parallelism来指定,然后对其进行校验,若parallelism<=0,且机器逻辑核心数-1后小于等于0,则赋值为1,若parallelism>MAX_CAP, 赋值为MAX_CAP(MAX_CAP=32767)。然后parallelism与SMASK(SMASK=65535)做与运算的结果再与mode(mode=0)做或运算【什么意思呢,就是parallelism最大不能超过65535,如果parallelism=0那么就返回0】。 然后config的值再与SMASK做与运算就是返回的最终值。
总结: ForkJoinPool.getCommonPoolParallelism()如果jvm启动参数配置了且有效(大于1小于32767),则返回的配置的值。如果没有配置又分两种情况,一机器逻辑核心数<=1,返回1;二机器逻辑核心数>1则返回(机器逻辑核心数-1)。