shutdownPerm:权限检查使用
runState:运行状态,对应有RUNNING 0、SHUTDOWN 1、STOP 2、TERMINATED 3
BlockingQueue
ReentrantLock mainLock:可重入锁
Condition termination=mainLock.newCondition() : 可重入锁变更条件
HashSet
volatile long keepAliveTime:线程存活时间
volatile boolean allowCoreThreadTimeOut:线程失败或者终止后能否使用keepAliveTime时间等待
volatile int corePoolSize;核心线程数量
volatile int maximumPoolSize;最大线程数量
volatile int poolSize;当前的线程数量
volatile RejectedExecutionHandler handler;拒绝执行Runnable后的处理器
volatile ThreadFactory threadFactory;线程工厂
RejectedExecutionHandler defaultHandler = new AbortPolicy();默认的失败处理策略
/**
* Executes the given task sometime in the future. The task
* may execute in a new thread or in an existing pooled thread.
*
* If the task cannot be submitted for execution, either because this
* executor has been shutdown or because its capacity has been reached,
* the task is handled by the current RejectedExecutionHandler.
*
* @param command the task to execute
* @throws RejectedExecutionException at discretion of
* RejectedExecutionHandler, if task cannot be accepted
* for execution
* @throws NullPointerException if command is null
*/
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
//如果当前线程大于核心线程或者加入works集合不成功,在这里已经执行了一次addIfUnderCorePoolSize加入works集合
if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) {
if (runState == RUNNING && workQueue.offer(command)) {
if (runState != RUNNING || poolSize == 0)
ensureQueuedTaskHandled(command);//确保队列任务正确插入
}
else if (!addIfUnderMaximumPoolSize(command))
reject(command); // is shutdown or saturated
}
}
private boolean addIfUnderCorePoolSize(Runnable firstTask) {
Thread t = null;
final ReentrantLock mainLock = this.mainLock;//在任务调度过程中用可重入锁mainlock进行并发控制
mainLock.lock();
try {
if (poolSize < corePoolSize && runState == RUNNING)
t = addThread(firstTask);
} finally {
mainLock.unlock();
}
if (t == null)
return false;
t.start();
return true;
}
private void ensureQueuedTaskHandled(Runnable command) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
boolean reject = false;
Thread t = null;
try {
int state = runState;
if (state != RUNNING && workQueue.remove(command))
reject = true;
else if (state < STOP &&
poolSize < Math.max(corePoolSize, 1) &&
!workQueue.isEmpty())
t = addThread(null);
} finally {
mainLock.unlock();
}
if (reject)
reject(command);
else if (t != null)
t.start();
}
/**
* The runLock is acquired and released surrounding each task
* execution. It mainly protects against interrupts that are
* intended to cancel the worker thread from instead
* interrupting the task being run.
*/
private final ReentrantLock runLock = new ReentrantLock();
我们看到有个runlock可重入锁定义,runlock用在中断方法interruptIfIdle以及执行任务的核心方法runtask中控制并发
源码中定义了一个thread对象用来执行中断thread.interrupt()以及执行shutdown时权限检查for (Worker w : workers)security.checkAccess(w.thread);
既然Thread这么重要,那Thread对象哪里来的?我们看源码addThread方法
/**
* Creates and returns a new thread running firstTask as its first
* task. Call only while holding mainLock.
*
* @param firstTask the task the new thread should run first (or
* null if none)
* @return the new thread, or null if threadFactory fails to create thread
*/
private Thread addThread(Runnable firstTask) {
Worker w = new Worker(firstTask);
Thread t = threadFactory.newThread(w);
if (t != null) {
w.thread = t;
workers.add(w);
int nt = ++poolSize;
if (nt > largestPoolSize)
largestPoolSize = nt;
}
return t;
}
其实这个Thread就是Worker的一个封装,一个装饰,Thread内部是一个Worker!所以他可以做到很多事情比如中断、权限检查等
/**
* Main run loop
*/
public void run() {
try {
Runnable task = firstTask;
firstTask = null;
while (task != null || (task = getTask()) != null) {
runTask(task);
task = null;
}
} finally {
workerDone(this);
}
}
work执行这个run方法时候,使用getTask方法获得任务,再看getTask
Runnable getTask() {
for (;;) {
try {
int state = runState;
if (state > SHUTDOWN)
return null;
Runnable r;
if (state == SHUTDOWN) // Help drain queue
r = workQueue.poll();
else if (poolSize > corePoolSize || allowCoreThreadTimeOut)
r = workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS);
else
r = workQueue.take();
if (r != null)
return r;
if (workerCanExit()) {
if (runState >= SHUTDOWN) // Wake up others
interruptIdleWorkers();
return null;
}
// Else retry
} catch (InterruptedException ie) {
// On interruption, re-check runState
}
}
}
我们最后整理一下思路,我们说worker是实现池的关键,为什么?
try {
Runnable task = firstTask;
firstTask = null;
while (task != null || (task = getTask()) != null) {
runTask(task);
task = null;
}
} finally {
workerDone(this);
}
关键有两个地方,while方法,只要getTask还有任务,,一直循环运行;如果没有任务了,workerDone,执行结束,然后调用workers.remove(w)把自己干掉,整个Worker就算完成任务。
正是因为Work是一个执行Runnable的Runnable,而且有一个自旋锁While以及getTask里的for循环,再加上corePoolSize、poolSize、maximumPoolSize、等这些变量维持和调节池的正常大小,实现了这个线程池!
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
补充:今天再回头研究ThreadPoolExcute时,阅读runTask方法,其调用getTask时,实际调用的是接口Queue的take方法,take方法是一个阻塞方法。在此备注一下:
take: 有则返回,删除底部元素,没有则阻塞除非中断
poll:有则返回,删除底部元素,没有则返回空,不阻塞
peek:有责返回,没有则返回空,但是不删除元素
remove:有责返回,并且删除元素,没有则报错