java线程池的简单运行过程
我们首先创建一个线程池,使用查看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则回收核心线程
} }
在这个流程中也解决了疑惑
线程池在创建时就初始化了corePoolSize个线程吗?
我们从源码中可以看出并不是,线程池初始创建的工作线程数为0.可以从ctl字段的初始值看出来。或者是当我们创建worker时,可以看到即便线程数小于corePoolSize,也是通过addWorker去创建新的worker,而不是从集合中取.

浙公网安备 33010602011771号