一直在用线程池,最近得闲,想看一下执行流程!顺便做个记录!看一眼构造方法
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) { //线程池线程和队列都无法添加任务时的回调!
if (corePoolSize < 0 || //判断核心个数不能小于0
maximumPoolSize <= 0 || //判断最线程个数不能小于0
maximumPoolSize < corePoolSize || //最小线程个数不能小于核心线程个数
keepAliveTime < 0) //包活时间不得为0
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
来看excute方法
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); //AtomicInteger类型的用来表示线程池的运行状和运行的worker数量
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get(); //AtomicInteger类型的用来表示线程池的运行状和运行的worker数量
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) //线程个数为0 直接添加
addWorker(null, false);
}
else if (!addWorker(command, false))//添加失败
reject(command); //拒绝处理
}
ctl AtomicInteger类型的用来表示线程池的运行状和运行的worker数量其中线程有
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;
这几种状态
excute方法,首先进来先判空
其次原子性的判断,如果线程个数小于核心线程数,就添加一个线程.return掉,否则进下一个判断如果该线程是运行状态running,并且插入runnable成功,则更新状态,里面又判断了ctl的状态,保证是最新的状态,如果不再运行且任务删除了就走reject()方法处理,这里调用了addworker方法还传了一个null进去,看看addworker如何处理
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) { //死循环
int c = ctl.get();
int rs = runStateOf(c);
// Check if queue empty only if necessary.
if (rs >= SHUTDOWN && //运行状态 是非running状态
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false; //处理null的情况,这里这几returnfalse了
for (;;) {
int wc = workerCountOf(c);//线程个数
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize)) //如果core = true wc和corePoolSize 对比,否则与maximumPoolSize 返回boolean值
return false; //默认返回false
if (compareAndIncrementWorkerCount(c)) //添加workercount 字段, 如果成功
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; //是否start成功
Worker w = null;
try {
w = new Worker(firstTask); //将线程封装在worker类中
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());
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
workers.add(w); //线程状态正常,添加到 workers队列中
int s = workers.size();
if (s > largestPoolSize) //队列大于最大线程数时,重新赋值! largestPoolSize初始在那里赋值呢?我并没有看到
largestPoolSize = s;
workerAdded = true;
}
} finally {
mainLock.unlock(); //释放锁
}
if (workerAdded) {
t.start(); //调用线程的start方法
workerStarted = true;//状态置为true
}
}
} finally {
if (! workerStarted)
addWorkerFailed(w);//失败会从workers队列删除!并原子性的减少 workercount
}
return workerStarted;
}
总结 :原子性的增加worker的count 在添加成功后!将线程封装在wroker类中,判断如果线程状态正常,则把worker 添加到一个worker对列中,并调用线程的 start方法!run方法执行!继而调用runworker方法看一下worker类
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this); //通过工程构建一个线程
}
public void run() {
runWorker(this);
}
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) || //线程状态状态>=stop状态
(Thread.interrupted() && //线程标记为终止
runStateAtLeast(ctl.get(), STOP))) && //ctl,每次用之前都要取一次,原子性!
!wt.isInterrupted())
wt.interrupt();
try {
beforeExecute(wt, task);
Throwable thrown = null;
try {
task.run(); //穿进来的task 得到了执行
} 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 { //如果执行过程中出现异常,到此时,completedAbruptly 任为true执行顺利则为false
processWorkerExit(w, completedAbruptly);
}
}
runworker 方法,在执行之前首先 unlock,此时允许中断!while判断不为null之后开始执行,立刻加锁!此时,不允许其他线程中断!在判断了当前线程的运行状态,没有被终止之后,执行了 封装在worker中的 runnable 的run方法,也就是通过线程池传进来的任务得到了执行,且当前worker的task以及getTask()获取的任务,有一方不为null则重复继续循环执行!没有任务可执行时则最终走processWorkerExit()线程退出方法!
接下来看一下gettask方法如何取得任务!
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())) { //队列为null, 那么workerCount不会被调整
decrementWorkerCount();
return null;
}
int wc = workerCountOf(c);
// Are workers subject to culling?
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize; //允许超时,个数>核心数 有一个为真则为真
if ((wc > maximumPoolSize || (timed && timedOut))//超出了最大线程数或者 满足 且count>1 队列为null 说明都需要减少线程了 则尝试减少workcount
&& (wc > 1 || workQueue.isEmpty())) {
if (compareAndDecrementWorkerCount(c))
return null;
continue;//如果减少workercount失败继续下次循环继续尝试减少!
}
try {
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) ://为真则 poll
workQueue.take(); //false 则阻塞等待
if (r != null) //不为null返回
return r;
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}
gettask方法 初始化超时tag 为false,
1》进入循环,当任务队列中有任务时开始判断若最大线程个数超过设置的最大数则尝试减少线程!
2》从队列取任务,若任务个数>核心线程个数,调用poll从任务队列workQueue首位取runnable,若任务个数<核心线程个数,通过take从队首取出数据,若取不出数据则则阻塞等待
继续processWorkerExit()线程退出方法
private void processWorkerExit(Worker w, boolean completedAbruptly) {
if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
decrementWorkerCount(); //runworker过程中出现异常,减少workercount
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)) { //状态小于stop 可能为shoutdown 和running状态
if (!completedAbruptly) { //执行过程中未出现异常
int min = allowCoreThreadTimeOut ? 0 : corePoolSize;//allowCoreThreadTimeOut 为真意味着 keeptimeout 超时后 核心线程会退出,min取0,否则取值为核心数
if (min == 0 && !workQueue.isEmpty()) //对列中有任务如果min为0,即不需要维持核心线程数量!至少保持一个线程
min = 1;
if (workerCountOf(c) >= min) //线程数量大于最小数,直接return不需要addworker()
return; // replacement not needed
}
addWorker(null, false);//workercount小于最小线程数的数量,就新添一个worker线程
}
}
final void tryTerminate() {
for (; ; ) {
int c = ctl.get();
if (isRunning(c) || //线程状态小于shutdown也就是running, 或 运行状态为shutdown,且任务队列不为null满足其一直接return
runStateAtLeast(c, TIDYING) ||
(runStateOf(c) == SHUTDOWN && !workQueue.isEmpty()))
return;
if (workerCountOf(c) != 0) { // Eligible to terminate
interruptIdleWorkers(ONLY_ONE); //线程终止 ONLY_ONE为true时只终止一个 反之
return;
}
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) { //TIDYING状态
try {
terminated();
} finally {
ctl.set(ctlOf(TERMINATED, 0));//,ctl记录的”任务数量”为0所有任务结束可以终止了
termination.signalAll();
}
return;
}
} finally {
mainLock.unlock();
}
// else retry on failed CAS
}
}
总结
1》如果completedAbruptly为true说明执行过程发生异常,直接尝试减少worker线程,加锁,从workers队列中移除worker
2》tryTerminate 方法,尝试终止线程,如果运行状态是running,或shutdown,或者队列中任然有任务则不终止,否则进行终止,ONLY_ONE为true则只终止一个,否则workers队列全部终止
3》线程是否需要停止,如果线程状态是TIDYING说明所有的任务已终止,ctl记录的”任务数量”为0,线程池会变为TIDYING状态将执行terminated()
4》如果线程状态是running 或 shutdown 如果当前线程是突然终止的,addWorker() 如果当前线程不是突然终止的,但当前线程数量 < 要维护的线程数量,addWorker() 如果调用线程池shutdown(),直到workQueue为空前,线程池都会维持corePoolSize个线程,然后再依次销毁!
总结:
简单来说线程池就是通过线程工厂创建了几个线程,这些线程内用for(;;)一直从阻塞队列里取任务,我们通过excute提交的任务最重都会进入这个阻塞队列。执行任务中,如果线程和阻塞队列都满额了,那么将会抛出一个回调,RejectedExecutionHandler,在这里我们处理是该丢掉任务,还是抛出异常,还是丢掉最老的任务,等等!任务执行完毕时,线程依次退出!