我们首先创建一个线程池,使用查看submit提交任务的方法,在这里我们以参数为提交callable为例,,线程池的submit方法的实现在AbstractExecutorService中实现,在submit方法中主要做了一下几件事情
1.参数校验
2.把我们的callable任务封装为一个RunnableFuture(通过newTaskfor方法,返回FutureTask,继承关系如下图)
3.调用线程池的execute方法执行处理任务逻辑
4.返回future
所以线程池如何管理线程处理任务也就是在第三步执行execute方法中,execute方法是顶层接口Executor的方法,具体实现要看实现类。我们经常使用的也就是ThreadPoolExecutor,所以就看ThreadPoolExecutor的execute方法
(继承关系)
//在下面的代码中出现的ctl是一个很重要的字段,它的作用是记录线程池的生命周期和当前工作的线程数,低29位表示工作线程的个数,高三位表示线程池的状态。
public void execute(Runnable command) { if (command == null) throw new NullPointerException(); 1.获取ctl的值 int c = ctl.get();
2.从ctl的值中获取线程池中线程池的个数,如果小于corePoolSize则使用addWork()方法创建线程执行任务 if (workerCountOf(c) < corePoolSize) { if (addWorker(command, true)) return; c = ctl.get(); }
3.如果当前工作线程个数大于corePoolSize则判断 线程池在运行状态 并且 任务添加到队列是否成功 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); }
4.线程个数大于corePoolSize且添加任务到任务队列失败,添加非corePoolSize线程,如果小于maxPoolSize,成功,若失败则拒绝 else if (!addWorker(command, false)) reject(command); }
我们创建处理任务的线程可以看出来实在addWorker()方法中进行的
线程池的五种状态,这五种状态的ctl值按下面排列递增
running:接受新任务并处理排队的任务
SHUTDOWN: 不接受新任务,但处理排队的任务
stop: 不接受新的任务,不处理排队的任务。并中断正在进行的任务
TIDYING。 所有的任务都结束了,workerCount为零。转换到TIDYING状态的线程
TERMINATED: terminated()已经完成
private boolean addWorker(Runnable firstTask, boolean core) { retry: for (;;) { int c = ctl.get();
获得线程池状态 int rs = runStateOf(c); // Check if queue empty only if necessary.
如果线程池状态>=shutdown 并且 (线程池状态不等于shutdown 或者任务为空或者任务队列为空) 则返回false if (rs >= SHUTDOWN && ! (rs == SHUTDOWN && firstTask == null && ! workQueue.isEmpty())) return false; for (;;) {
获取当前工作线程的数量 int wc = workerCountOf(c);
如果线程数量大于等于capacity(线程池允许最大数量)或者线程数量大于核心(最大)线程数则返回false if (wc >= CAPACITY || wc >= (core ? corePoolSize : maximumPoolSize)) return false; if (compareAndIncrementWorkerCount(c))线程池数量+1 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;从创建的Worker中取得创建的线程 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()); 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) { t.start();启动线程 workerStarted = true; } } } finally { if (! workerStarted) addWorkerFailed(w); } return workerStarted; }
worker代码如下,worker也继承了runable接口,所以重写了run方法Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker this.firstTask = firstTask;我们传入的任务 this.thread = getThreadFactory().newThread(this);从ThreadFactory中获得线程,并且把当前worker(this)传入了进去,所以当该线程start时,调用的也就是当前worker的run方法 }
worker的run方法又调用了runworker(this)方法,所以我们去看runworker方法
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();创建的线程 Runnable task = w.firstTask;传入的futureTask任务 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();调用了一开始的futureTask的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,继续从任务队列中取任务,完成的任务数++ task = null; w.completedTasks++; w.unlock(); } } completedAbruptly = false; } finally { processWorkerExit(w, completedAbruptly);
正常退出后在里面进行线程的rmove工作
并且会尝试终止线程池
并且会根据参数配置是否回收核心线程,如果allowCoreThreadTimeOut为true则回收核心线程
} }
在这个流程中也解决了我的两个疑惑
1.线程池在创建时就初始化了corePoolSize个线程吗?
我们从源码中可以看出并不是,线程池初始创建的工作线程数为0.可以从ctl字段的初始值看出来。或者是当我们创建worker时,可以看到即便线程数小于corePoolSize,也是通过addWorker去创建新的worker,而不是从集合中取.
2.核心线程不会被回收吗
在最后一步当线程获取不到任务执行processWorkerExit()方法时,会执行workers.remove(worker)方法。如果配置了allowCoreThreadTimeOut为false,那么 会新创建一个没有task的线程。如果allowCoreThreadTimeOut为true,则最小线程数为0
private void processWorkerExit(Worker w, boolean completedAbruptly) { if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted decrementWorkerCount(); final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { completedTaskCount += w.completedTasks; workers.remove(w); } finally { mainLock.unlock(); } tryTerminate(); int c = ctl.get(); if (runStateLessThan(c, STOP)) { if (!completedAbruptly) { int min = allowCoreThreadTimeOut ? 0 : corePoolSize; if (min == 0 && ! workQueue.isEmpty()) min = 1; if (workerCountOf(c) >= min) return; // replacement not needed } addWorker(null, false); } }