ForkJoinPool线程池是jdk 1.7引入的新线程池实现,那么它与之前1.5引入的ThreadPoolExecutor有什么不同呢?带着问题学习源码咯。本文仅简单学习,不深入(怕翻车-_-!)
从简单的无参构造器入手吧
public ForkJoinPool() {
this(Math.min(MAX_CAP, Runtime.getRuntime().availableProcessors()),
defaultForkJoinWorkerThreadFactory, null, false);
}
public ForkJoinPool(int parallelism,
ForkJoinWorkerThreadFactory factory,
UncaughtExceptionHandler handler,
boolean asyncMode) {
this(checkParallelism(parallelism),
checkFactory(factory),
handler,
asyncMode ? FIFO_QUEUE : LIFO_QUEUE,
"ForkJoinPool-" + nextPoolId() + "-worker-");
checkPermission();
}
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);
}
private static int checkParallelism(int parallelism) {
if (parallelism <= 0 || parallelism > MAX_CAP)
throw new IllegalArgumentException();
return parallelism;
}
static final int MAX_CAP = 0x7fff; // max #workers - 1
RSLOCK = 1;
RSIGNAL = 1 << 1;
STARTED = 1 << 2;
STOP = 1 << 29;
TERMINATED = 1 << 30;
SHUTDOWN = 1 << 31;
提交任务会将Runnable、Callable接口的实现类task封装为ForkJoinTask提交至线程池,我们重点关注任务进入线程池后的动作externalPush
public <T> ForkJoinTask<T> submit(Callable<T> task) {
ForkJoinTask<T> job = new ForkJoinTask.AdaptedCallable<T>(task);
externalPush(job);
return job;
}
externalPush将任务入队
final void externalPush(ForkJoinTask<?> task) {
WorkQueue[] ws; WorkQueue q; int m;
// 1. 获取当前线程探针
int r = ThreadLocalRandom.getProbe();
// 2. rs初始值为0
int rs = runState;
// 3.1 将任务压入队列
if ((ws = workQueues) != null && (m = (ws.length - 1)) >= 0 &&
(q = ws[m & r & SQMASK]) != null && r != 0 && rs > 0 &&
U.compareAndSwapInt(q, QLOCK, 0, 1)) {
// 3.1.1 线程池已经启动
// 3.1.2 线程池任务队列已初始化
// 3.1.3 随机获取一个任务队列,对该队列加锁
// 3.1.4 将任务压入任务队列
ForkJoinTask<?>[] a; int am, n, s;
if ((a = q.array) != null &&
(am = a.length - 1) > (n = (s = q.top) - q.base)) {
int j = ((am & s) << ASHIFT) + ABASE;
U.putOrderedObject(a, j, task);
U.putOrderedInt(q, QTOP, s + 1);
U.putIntVolatile(q, QLOCK, 0);
// 3.1.5 如果拉取数据的slot槽索引+1已经大于等于压入数据的slot槽索引
if (n <= 1)
// 3.1.6 尝试唤醒worker或创建worker(有任务入队列可以干活了,
// 如果人手不够会尝试创建更多的工人,前提是预算允许的话)
signalWork(ws, q);
return;
}
U.compareAndSwapInt(q, QLOCK, 1, 0);
}
// 3.2 直接提交任务
externalSubmit(task);
}
private void externalSubmit(ForkJoinTask<?> task) {
// 如果当前线程探针未初始化则初始化探针,并获取探针
int r; // initialize caller's probe
if ((r = ThreadLocalRandom.getProbe()) == 0) {
ThreadLocalRandom.localInit();
r = ThreadLocalRandom.getProbe();
}
// 自旋
for (;;) {
WorkQueue[] ws; WorkQueue q; int rs, m, k;
boolean move = false;
...
// 如果线程池任务队列数组未初始化,则初始化任务队列数组
else if ((rs & STARTED) == 0 || // initialize
((ws = workQueues) == null || (m = ws.length - 1) < 0)) {
int ns = 0;
rs = lockRunState();
try {
if ((rs & STARTED) == 0) {
...
workQueues = new WorkQueue[n];
ns = STARTED;
}
} finally {
unlockRunState(rs, (rs & ~RSLOCK) | ns);
}
}
// 如果选中的任务队列数组下标处的队列非空,将任务压入队列
else if ((q = ws[k = r & m & SQMASK]) != null) {
if (q.qlock == 0 && U.compareAndSwapInt(q, QLOCK, 0, 1)) {
ForkJoinTask<?>[] a = q.array;
int s = q.top;
boolean submitted = false; // initial submission or resizing
try { // locked version of push
// 队列存储剩余空间或者队列还有可扩容的空间,则将任务压入队列
if ((a != null && a.length > s + 1 - q.base) ||
(a = q.growArray()) != null) {
int j = (((a.length - 1) & s) << ASHIFT) + ABASE;
U.putOrderedObject(a, j, task);
U.putOrderedInt(q, QTOP, s + 1);
submitted = true;
}
} finally {
U.compareAndSwapInt(q, QLOCK, 1, 0);
}
// 尝试唤醒工作者(有任务入队列可以干活了)
if (submitted) {
signalWork(ws, q);
return;
}
}
move = true; // move on failure
}
// 初始化任务队列(注意队列未绑定工作者即等待处理)并放入任务队列数组
else if (((rs = runState) & RSLOCK) == 0) { // create new queue
q = new WorkQueue(this, null);
q.hint = r;
q.config = k | SHARED_QUEUE;
q.scanState = INACTIVE;
rs = lockRunState(); // publish index
if (rs > 0 && (ws = workQueues) != null &&
k < ws.length && ws[k] == null)
ws[k] = q; // else terminated
unlockRunState(rs, rs & ~RSLOCK);
}
else
// 当前线程太忙了,换个工人
move = true; // move if busy
if (move)
// 当前队列已满移动探针,寻找其他空闲队列
r = ThreadLocalRandom.advanceProbe(r);
}
}
final void signalWork(WorkQueue[] ws, WorkQueue q) {
long c; int sp, i; WorkQueue v; Thread p;
// 如果当前活跃工作者太少则尝试创建
while ((c = ctl) < 0L) { // too few active
// 当前活跃工作者不存在空闲的工作者
if ((sp = (int)c) == 0) { // no idle workers
// 工作者过少
if ((c & ADD_WORKER) != 0L) // too few workers
// 尝试创建工作者
tryAddWorker(c);
break;
}
...
if ((v = ws[i]) == null) // terminating
break;
int vs = (sp + SS_SEQ) & ~INACTIVE; // next scanState
int d = sp - v.scanState; // screen CAS
long nc = (UC_MASK & (c + AC_UNIT)) | (SP_MASK & v.stackPred);
if (d == 0 && U.compareAndSwapLong(this, CTL, c, nc)) {
// 任务队列当前处于活跃状态(有任务),如果存在工作者则唤醒工作者干活
v.scanState = vs; // activate v
if ((p = v.parker) != null)
U.unpark(p);
break;
}
// 没有更多的待处理任务,退出
if (q != null && q.base == q.top) // no more work
break;
}
}
创建工作者
private void tryAddWorker(long c) {
...
createWorker();
...
}
private boolean createWorker() {
ForkJoinWorkerThreadFactory fac = factory;
...
if (fac != null && (wt = fac.newThread(this)) != null) {
wt.start();
return true;
...
}
线程工厂构建线程(工作者)
static final class DefaultForkJoinWorkerThreadFactory
implements ForkJoinWorkerThreadFactory {
public final ForkJoinWorkerThread newThread(ForkJoinPool pool) {
return new ForkJoinWorkerThread(pool);
}
}
protected ForkJoinWorkerThread(ForkJoinPool pool) {
...
// 注册当前worker
this.workQueue = pool.registerWorker(this);
}
线程池注册worker
final WorkQueue registerWorker(ForkJoinWorkerThread wt) {
UncaughtExceptionHandler handler;
wt.setDaemon(true); // configure thread
if ((handler = ueh) != null)
wt.setUncaughtExceptionHandler(handler);
// 初始化时队列中没有待处理任务
WorkQueue w = new WorkQueue(this, wt);
int i = 0; // assign a pool index
int mode = config & MODE_MASK;
int rs = lockRunState();
try {
WorkQueue[] ws; int n; // skip if no array
if ((ws = workQueues) != null && (n = ws.length) > 0) {
...
w.hint = s; // use as random seed
// 线程池中的index与模式mode
w.config = i | mode;
w.scanState = i; // publication fence
ws[i] = w;
}
} ...
wt.setName(workerNamePrefix.concat(Integer.toString(i >>> 1)));
return w;
}
执行工作者线程,工作者线程遍历任务队列数组,选择存在“待处理任务”的队列,遍历队列拉取“待处理任务”并执行
// 入参r被限制不能为0,依然能选择到workQueues中下标为0的任务队列,
// 因为r为随机数对队列(数组长度-1)进行取余,随机数可以整除(数组长度-1)时下标为0
private ForkJoinTask<?> scan(WorkQueue w, int r) {
WorkQueue[] ws; int m;
if ((ws = workQueues) != null && (m = ws.length - 1) > 0 && w != null) {
int ss = w.scanState; // initially non-negative
for (int origin = r & m, k = origin, oldSum = 0, checkSum = 0;;) {
WorkQueue q; ForkJoinTask<?>[] a; ForkJoinTask<?> t;
int b, n; long c;
if ((q = ws[k]) != null) {
if ((n = (b = q.base) - q.top) < 0 &&
(a = q.array) != null) { // non-empty
long i = (((a.length - 1) & b) << ASHIFT) + ABASE;
if ((t = ((ForkJoinTask<?>)
U.getObjectVolatile(a, i))) != null &&
q.base == b) {
if (ss >= 0) {
if (U.compareAndSwapObject(a, i, t, null)) {
q.base = b + 1;
if (n < -1) // signal others
signalWork(ws, q);
return t;
}
}
...
// 移动后再次扫描
r ^= r << 1; r ^= r >>> 3; r ^= r << 10;
origin = k = r & m; // move and rescan
}