1.前言
线程池作为java 并发领域的一个重要组成部分,也是面试必问的考点,理论性的东西我这里就不一一说明了,推荐一篇写得很好的文章,来自美团技术团队
https://tech.meituan.com/2020/04/02/java-pooling-pratice-in-meituan.html
我个人觉得理论性的东西可能大家都懂,但是具体的实现细节可能并不是很清楚所以才想记录一下,加深记忆。
2.关键源码解析
(1)ctl
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); private static final int COUNT_BITS = Integer.SIZE - 3; private static final int CAPACITY = (1 << COUNT_BITS) - 1; // runState is stored in the high-order bits private static final int RUNNING = -1 << COUNT_BITS; private static final int SHUTDOWN = 0 << COUNT_BITS; private static final int STOP = 1 << COUNT_BITS; private static final int TIDYING = 2 << COUNT_BITS; private static final int TERMINATED = 3 << COUNT_BITS; // Packing and unpacking ctl private static int runStateOf(int c) { return c & ~CAPACITY; } private static int workerCountOf(int c) { return c & CAPACITY; } private static int ctlOf(int rs, int wc) { return rs | wc; }
ctl 一共32位,高3位表示线程池的状态,剩下的29位表示运行中的线程数
(2) execute(Runnable command)
int c = ctl.get(); //当前线程数小于核心线程数 if (workerCountOf(c) < corePoolSize) { //创建核心线程,并执行任务 if (addWorker(command, true)) return; c = ctl.get(); } //当前线程数大于等于核心线程数 //检查线程池状态,并将任务添加到队列中,可以添加成功代表队列未满 if (isRunning(c) && workQueue.offer(command)) { int recheck = ctl.get(); if (! isRunning(recheck) && remove(command)) reject(command); //启动非核心线程,处理队列中的任务 else if (workerCountOf(recheck) == 0) addWorker(null, false); } //队列已满,产生添加非核心线程,执行任务,如果失败则拒绝任务 else if (!addWorker(command, false)) reject(command);
(3) addWorker(Runnable firstTask, boolean core)
Worker 这个类继承了aqs 并且实现了Runnable 接口,所以它具有一个锁的功能,它的run()方法最终调用了ThreadPoolExecutor 的 runWorker 方法,runWoorker()中通过getTask()获取任务,并且执行了任务的run()方法
private boolean addWorker(Runnable firstTask, boolean core) { retry: for (;;) { int c = ctl.get(); int rs = runStateOf(c); // 校验线程池状态 if (rs >= SHUTDOWN && ! (rs == SHUTDOWN && firstTask == null && ! workQueue.isEmpty())) return false; for (;;) { int wc = workerCountOf(c); //检查线程数量是否超过限制 if (wc >= CAPACITY || wc >= (core ? corePoolSize : maximumPoolSize)) return false; if (compareAndIncrementWorkerCount(c)) break retry; c = ctl.get(); // Re-read ctl if (runStateOf(c) != rs) continue retry; // else CAS failed due to workerCount change; retry inner loop } } boolean workerStarted = false; boolean workerAdded = false; Worker w = null; try { w = new Worker(firstTask); final Thread t = w.thread; if (t != null) { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { // Recheck while holding lock. // Back out on ThreadFactory failure or if // shut down before lock acquired. int rs = runStateOf(ctl.get()); //workers 是存储当前运行任务的线程 if (rs < SHUTDOWN || (rs == SHUTDOWN && firstTask == null)) { if (t.isAlive()) // precheck that t is startable throw new IllegalThreadStateException(); workers.add(w); int s = workers.size(); if (s > largestPoolSize) largestPoolSize = s; workerAdded = true; } } finally { mainLock.unlock(); } if (workerAdded) { //启动worker ,执行worker的run方法 t.start(); workerStarted = true; } } } finally { if (! workerStarted) addWorkerFailed(w); } return workerStarted; }
woker 的run方法执行调用 runWorker ,并传入自身
final void runWorker(Worker w) { Thread wt = Thread.currentThread(); //第一个任务,如果不为空则立刻执行,否则从队列获取 Runnable task = w.firstTask; w.firstTask = null; w.unlock(); // allow interrupts boolean completedAbruptly = true; try { while (task != null || (task = getTask()) != null) { w.lock(); // If pool is stopping, ensure thread is interrupted; // if not, ensure thread is not interrupted. This // requires a recheck in second case to deal with // shutdownNow race while clearing interrupt if ((runStateAtLeast(ctl.get(), STOP) || (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) && !wt.isInterrupted()) wt.interrupt(); try { beforeExecute(wt, task); Throwable thrown = null; try { //执行task的run方法,这里执行的东西就是我们提交的任务 task.run(); } catch (RuntimeException x) { thrown = x; throw x; } catch (Error x) { thrown = x; throw x; } catch (Throwable x) { thrown = x; throw new Error(x); } finally { afterExecute(task, thrown); } } finally { task = null; w.completedTasks++; w.unlock(); } } completedAbruptly = false; } finally {
//删除非核心线程 processWorkerExit(w, completedAbruptly); } }
private Runnable getTask() { boolean timedOut = false; // Did the last poll() time out? for (;;) { int c = ctl.get(); int rs = runStateOf(c); // Check if queue empty only if necessary. if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) { decrementWorkerCount(); return null; } int wc = workerCountOf(c); // Are workers subject to culling? //是否允许所有线程超时,或者当前工作线程大于核心线程数,所有线程都可以超时意思就是核心线程和非核心线程没什么区别 boolean timed = allowCoreThreadTimeOut || wc > corePoolSize; //超时则返回空 if ((wc > maximumPoolSize || (timed && timedOut)) && (wc > 1 || workQueue.isEmpty())) { if (compareAndDecrementWorkerCount(c)) return null; continue; } try { //如果可以超时,从队列获取任务,会先阻塞一定时间,超过时间会抛出异常,表示超时,不可超时时时take会一直阻塞,直到有任务加入 Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : workQueue.take(); if (r != null) return r; timedOut = true; } catch (InterruptedException retry) { timedOut = false; } } }