ThreadPool源码分析-jdk6
execute方法分析
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
//poolSize初始值为0,先启动corePoolSize数量的线程执行
if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) {
//poolSize==corePoolSize 后 将task加入队列
if (runState == RUNNING && workQueue.offer(command)) {
if (runState != RUNNING || poolSize == 0)
ensureQueuedTaskHandled(command);
}
//如果队列容量不够 且 poolSize < maximumPoolSize 则直接启动
else if (!addIfUnderMaximumPoolSize(command))
reject(command); // is shutdown or saturated
}
}
private boolean addIfUnderCorePoolSize(Runnable firstTask) {
Thread t = null;
final ReentrantLock mainLock = this.mainLock;
//下面代码中有根据共享变量判断的处理,为了防止并发问题,此处加锁。
mainLock.lock();
try {
if (poolSize < corePoolSize && runState == RUNNING)
//增加一个新的线程启动并执行任务
//此处重要
t = addThread(firstTask);
} finally {
mainLock.unlock();
}
return t != null;
}
private Thread addThread(Runnable firstTask) {
Worker w = new Worker(firstTask);
Thread t = threadFactory.newThread(w);
boolean workerStarted = false;
if (t != null) {
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
w.thread = t;
workers.add(w);
int nt = ++poolSize;//工作线程将启动 增加工作线程数。
if (nt > largestPoolSize)
largestPoolSize = nt;
try {
//这里启动提交的任务
//重点是worker 的run实现
t.start();
workerStarted = true;
}
finally {
if (!workerStarted)
workers.remove(w);
}
}
return t;
}
下面看一下worker的重要方法
/**
* Main run loop
*/
//不断获取队列中的任务串行执行。
//其中 getTask(), runTask(task)是重要的方法
//while循环先执行执行提交的任务(addThread 中的 firstTask),然后从队列中取出任务执行
如果队列中无任务 则阻塞(依赖BlockingQueue的take()实现),直到取得一个任务为止。
public void run() {
try {
hasRun = true;
Runnable task = firstTask;
firstTask = null;
while (task != null || (task = getTask()) != null) {
runTask(task);//同步执行
task = null;
}
} finally {
//执行完成 --poolSize
workerDone(this);
}
}
}
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
}
}
}
private void runTask(Runnable task) {
final ReentrantLock runLock = this.runLock;
//这里加锁 为修改 共享变量数据安全
runLock.lock();
try {
//如果不是stop状态 就要清除打断标识,保证当前线程后续阻塞执行不会被打断(Thread.interrupted()有返回打断状态,清除打断标识的作用)
//如果是stop状态 就要保存打断状态,保证当前线程后续执行会被打断
if ((runState >= STOP ||
(Thread.interrupted() && runState >= STOP)) &&
hasRun)
thread.interrupt();
//跟踪执行状态确保afterExecute在任务完成后或执行任务中抛出异常后被调用
否则可能在执行afterExecute过程中抛出 runtime异常,这种情况我们不想再次执行它。(执行afterExecute的一个细致考虑。)
boolean ran = false;
//执行任务前和执行任务后都留了一个钩子
beforeExecute(thread, task);
try {
task.run();
ran = true;
afterExecute(task, null);
++completedTasks;
} catch (RuntimeException ex) {
if (!ran)
afterExecute(task, ex);
throw ex;
}
} finally {
runLock.unlock();
}
}
// poolSize < maximumPoolSize 则直接启动
private boolean addIfUnderMaximumPoolSize(Runnable firstTask) {
Thread t = null;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
if (poolSize < maximumPoolSize && runState == RUNNING)
t = addThread(firstTask);
} finally {
mainLock.unlock();
}
return t != null;
}
使用ExecutorService pool = Executors.newFixedThreadPool(2);
时的队列是LinkedBlockingQueue,其容量最大值是Integer.MAX_VALUE.
所以正常情况下不会将 queue装满,不会执行到addIfUnderMaximumPoolSize()
问题
queue什么时候能满
queue的大小需要看传入的queue的容量。
拒绝策略怎么执行
在任务数超过maximumPoolSize时根据传入的拒绝策略执行不同的处理
AbortPolicy: 中止策略,直接抛出异常 默认
AbortPolicyWithReport:写warn日志并抛出异常
CallerRunsPolicy:调用run方法策略,如果没有shutdown 则直接调用run方法。
DiscardPolicy:丢弃策略,什么都不做。
DiscardOldestPolicy:丢弃旧任务策略,丢弃旧任务,执行新任务。
NewThreadRunsPolicy:创建新线程执行策略,创建新线程执行,失败抛出异常。
shutdown(),shutdownNow源码分析
public void shutdown() {
SecurityManager security = System.getSecurityManager();
if (security != null)
security.checkPermission(shutdownPerm);
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
if (security != null) { // Check if caller can modify our threads
for (Worker w : workers)
security.checkAccess(w.thread);
}
int state = runState;
if (state < SHUTDOWN)
runState = SHUTDOWN;
try {
for (Worker w : workers) {
//重点是这段
w.interruptIfIdle();
}
} catch (SecurityException se) { // Try to back out
runState = state;
// tryTerminate() here would be a no-op
throw se;
}
tryTerminate(); //如果线程池和队列为空执行终止处理
} finally {
mainLock.unlock();
}
}
/**
如果线程没有运行任务,就打断。
* Interrupts thread if not running a task.
*/
void interruptIfIdle() {
final ReentrantLock runLock = this.runLock;
if (runLock.tryLock()) {
//runLock 这个lock与runTask()用的是同一个,作用是等待任务执行完成
try {//hasRun在worker 中默认是false, 执行run方法后被赋值true
if (hasRun && thread != Thread.currentThread())
// 打断线程。getTask()做出相应处理
thread.interrupt();
} finally {
runLock.unlock();
}
}
}
//回头看run()和getTask()并结合对interrupt()分析
程序的运行会有两种情况
- 没有阻塞 正在运行中
- 执行到 getTask()的 r = workQueue.take(); 进入阻塞
情况1 最终会执行 getTask()的 r = workQueue.poll(); r=null,然后执行 workerDone(this);
情况2 抛出InterruptedException异常,在getTask中异常被捕获,进入循环,执行情况1的逻辑
重点代码注释如下:
Runnable getTask() {
for (;;) {
try {
int state = runState;
if (state > SHUTDOWN)
return null;
Runnable r;
if (state == SHUTDOWN) // Help drain queue
//当执行shutDown()后,run follow code,poll方法不会阻塞.
r = workQueue.poll();
else if (poolSize > corePoolSize || allowCoreThreadTimeOut)
//allowCoreThreadTimeOut 默认false,keepAliveTime是构造方法传进来的。线值程池类型是 cached的时候,值是60s
//当工作线程数超出核心线程数时,调用超时拉取方法。
r = workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS);
else
//队列为空进入阻塞
r = workQueue.take();
if (r != null)
return r;
if (workerCanExit()) {//runState >= STOP 或队列为空 或运行核心线程timeout 且工作线程数据大于核心线程数
//其他的线程可能出于阻塞状态,用interrupt唤醒
if (runState >= SHUTDOWN) // Wake up others
interruptIdleWorkers();
return null;
}
// Else retry
} catch (InterruptedException ie) {
// On interruption, re-check runState
}
}
}
catch (InterruptedException ie)这段是容易忽略的地方。为了执行workQueue.take();进入阻塞状态的线程准备,保证能进入循环。
public void run() {
try {
hasRun = true;
Runnable task = firstTask;
firstTask = null;
// 通过task != null来控制是否终止循环。
while (task != null || (task = getTask()) != null) {
runTask(task);
task = null;
}
} finally {
workerDone(this);
}
}
}
//完成清理任务,如移除worker,执行队列中剩余的任务。
void workerDone(Worker w) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
completedTaskCount += w.completedTasks;
workers.remove(w);
if (--poolSize == 0)
tryTerminate();
} finally {
mainLock.unlock();
}
}
//如果线程池和队列为空执行终止处理
private void tryTerminate() {
if (poolSize == 0) {
int state = runState;
//执行队列中剩余的任务
if (state < STOP && !workQueue.isEmpty()) {
state = RUNNING; // disable termination check below
//创建一个空任务的woker处理执行关闭期间添加进队列的任务,实现了拉灯处理
addThread(null);
}
//标识线程池位终止状态,解除termination的wait状态
if (state == STOP || state == SHUTDOWN) {
runState = TERMINATED;
termination.signalAll();
terminated();//目前是空实现
}
}
}
如果此时再添加任务,则不会被添加,执行拒绝策略
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) {
//shutdown()执行后运行到这,shutdown状态 workQueue.offer(command)不执行
if (runState == RUNNING && workQueue.offer(command)) {
if (runState != RUNNING || poolSize == 0)
ensureQueuedTaskHandled(command);
}
//shutdown状态 不执行
else if (!addIfUnderMaximumPoolSize(command))
//执行拒绝策略
reject(command); // is shutdown or saturated
}
}
private boolean addIfUnderCorePoolSize(Runnable firstTask) {
Thread t = null;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
//shutdown状态 不执行
if (poolSize < corePoolSize && runState == RUNNING)
t = addThread(firstTask);
} finally {
mainLock.unlock();
}
return t != null;
}
shutdownNow 与shutdown不同之处
- runState is set to STOP,
- 所有工作线程被打断,不仅空闲的。
- 队列被耗尽,并返回。
public List<Runnable> shutdownNow() {
/*
* shutdownNow differs from shutdown only in that
* 1. runState is set to STOP,
* 2. all worker threads are interrupted, not just the idle ones, and
* 3. the queue is drained and returned.
*/
SecurityManager security = System.getSecurityManager();
if (security != null)
security.checkPermission(shutdownPerm);
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
if (security != null) { // Check if caller can modify our threads
for (Worker w : workers)
security.checkAccess(w.thread);
}
int state = runState;
if (state < STOP)
runState = STOP;
try {
for (Worker w : workers) {
//不管是否是执行中,都调用打断。
w.interruptNow();
}
} catch (SecurityException se) { // Try to back out
runState = state;
// tryTerminate() here would be a no-op
throw se;
}
//耗尽并获取队列剩余任务
List<Runnable> tasks = drainQueue();
tryTerminate(); // Terminate now if pool and queue empty
return tasks;
} finally {
mainLock.unlock();
}
}
mainLock和runLock的作用?
runLock在runTask(Runnable task) 和interruptIfIdle()中使用,目的是为了interruptIfIdle不影响正在执行的任务。interruptNow 没有使用runlock,即使任务在执行,也打断。
//当改变poolSize, corePoolSize, maximumPoolSize, runState, and workers set.这些共享变量时,保证数据安全
private final ReentrantLock mainLock = new ReentrantLock();
Worker.thread?
Worker.thread 是新创建的线程
//创建代码如下
实现类:DefaultThreadFactory implements ThreadFactory
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
if (t.isDaemon())
t.setDaemon(false);?
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);?
return t;
}
来源:CSDN
作者:chenchangqun11
链接:https://blog.csdn.net/chenchangqun11/article/details/104074882