一、前言
2016年即将过去,要抓紧时间,夯实java基础知识部分,为以后学习的新的知识做准备。
二、线程池基本原理图
三、ThreadPoolExecutor的内部结构
1.Worker在里面是一个核心的内部类
private final class Worker
extends AbstractQueuedSynchronizer
implements Runnable
{
/**
* This class will never be serialized, but we provide a
* serialVersionUID to suppress a javac warning.
*/
private static final long serialVersionUID = 6138294804551838833L;
/** Thread this worker is running in. Null if factory fails. */
final Thread thread;
/** Initial task to run. Possibly null. */
Runnable firstTask;
/** Per-thread task counter */
volatile long completedTasks;
//...
}
构造方法
//由线程工厂创建一个任务线程
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}
部分方法:
/** 将由ThreadPoolExecutor的runWorker执行*/
public void run() {
runWorker(this);
}
2.类的属性
// 线程池的控制状态(用来表示线程池的运行状态(整形的高3位)和运行的worker数量(低29位)
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
// 29位的偏移量
private static final int COUNT_BITS = Integer.SIZE - 3;
// 最大容量(2^29 - 1)
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
// runState is stored in the high-order bits
// 线程运行状态,总共有5个状态,需要3位来表示(所以偏移量的29 = 32 - 3)
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;
//阻塞队列
private final BlockingQueue<Runnable> workQueue;
//主方法重入锁
private final ReentrantLock mainLock = new ReentrantLock();
//工作线程集合
private final HashSet<Worker> workers = new HashSet<Worker>();
//终止条件
private final Condition termination = mainLock.newCondition();
//最大池大小
private int largestPoolSize;
//完成任务的数量
private long completedTaskCount;
//线程工厂
private volatile ThreadFactory threadFactory;
//拒绝处理器接口
private volatile RejectedExecutionHandler handler;
//保持的时间
private volatile long keepAliveTime;
//允许线程的超时时间
private volatile boolean allowCoreThreadTimeOut;
//核心线程池的大小
private volatile int corePoolSize;
//最大线程池大小
private volatile int maximumPoolSize;
//默认拒绝处理器
private static final RejectedExecutionHandler defaultHandler =
new AbortPolicy();
3.构造方法
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,Executors.defaultThreadFactory(), defaultHandler);
}
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,threadFactory, defaultHandler);
}
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,Executors.defaultThreadFactory(), handler);
}
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 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;
}
4.部分方法
4.1 public void execute(Runnable command)方法
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
/*
* 进行下面三步
*
* 1. 如果运行的线程小于corePoolSize,则尝试使用用户定义的Runnalbe对象创建一个新的线程
* 调用addWorker函数会原子性的检查runState和workCount,通过返回false来防止在不应
* 该添加线程时添加了线程
* 2. 如果一个任务能够成功入队列,在添加一个线城时仍需要进行双重检查(因为在前一次检查后
* 该线程死亡了),或者当进入到此方法时,线程池已经shutdown了,所以需要再次检查状态,
* 若有必要,当停止时还需要回滚入队列操作,或者当线程池没有线程时需要创建一个新线程
* 3. 如果无法入队列,那么需要增加一个新线程,如果此操作失败,那么就意味着线程池已经shut
* down或者已经饱和了,所以拒绝任务
*/
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {//小于核心线程池大小
if (addWorker(command, true))//新增Worker
return;
c = ctl.get();//再次获取线程状态
}
// 当线程池中的任务数量 >= "核心池大小"时,
// 而且,"线程池处于允许状态"时,则尝试将任务添加到阻塞队列中。
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
// 否则,如果"线程池中任务数量"为0,则通过addWorker(null, false)
//尝试新建一个线程,新建线程对应的任务为null。
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false))//添加线程失败
//拒绝执行
reject(command);
}
4.2private boolean addWorker(Runnable firstTask, boolean core)添加工作线程
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {
int c = ctl.get(); 获取ctl对应的int值。该int值保存了"线程池中任务的数量"和"线程池状态"信息
int rs = runStateOf(c);//获取线程池的状态
// 对队列和状态进行检查
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
for (;;) {
int wc = workerCountOf(c);//线程池任务数量
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))//超过容量返回false
return false;
if (compareAndIncrementWorkerCount(c))//工作线程数量增加
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 {
final ReentrantLock mainLock = this.mainLock;
w = new Worker(firstTask);//添加工作线程
final Thread t = w.thread;
if (t != null) {
mainLock.lock();
try {
// Recheck while holding lock.
// Back out on ThreadFactory failure or if
// shut down before lock acquired.
//获取线程池的信息再次判断
int c = ctl.get();
int rs = runStateOf(c);
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);//线程集合将会移除工作线程并将线程池的数量减1
}
return workerStarted;//返回工作线程运行的状态
}
4.3private void addWorkerFailed(Worker w) 线程启动失败
private void addWorkerFailed(Worker w) 线程启动失败
private void addWorkerFailed(Worker w) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
//线程集合将会移除工作线程并将线程池的数量减1
if (w != null)
workers.remove(w);
decrementWorkerCount();
tryTerminate();
} finally {
mainLock.unlock();
}
}
4.4线程池关闭相关的方法
/**
依次的关闭线程,之前已提交的任务将会执行完成,但是不会接受新的任务,
如果已关闭再次调用不会有额外的影响。
*/
public void shutdown() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();//检查关闭的权限
advanceRunState(SHUTDOWN);//设置关闭
interruptIdleWorkers();中断空闲的工作线程
onShutdown(); // hook for ScheduledThreadPoolExecutor
} finally {
mainLock.unlock();
}
tryTerminate();
}
/**
试图去停止所有的运行的线程,终止所有等待的任务,并将等待的任务用集合返回,
清空任务队列的信息并返回。
*/
public List<Runnable> shutdownNow() {
List<Runnable> tasks;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();//检查关闭权限
advanceRunState(STOP);设置停止
interruptWorkers();//中断所有线程
tasks = drainQueue();//释放队列并返回未执行的任务
} finally {
mainLock.unlock();
}
tryTerminate();
return tasks;
}
public boolean isShutdown() {
return ! isRunning(ctl.get()); //检查线程池是否关闭
}
//中断所有空闲线程
private void interruptIdleWorkers(boolean onlyOne) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (Worker w : workers) {
Thread t = w.thread;
if (!t.isInterrupted() && w.tryLock()) {
try {
t.interrupt();//中断线程
} catch (SecurityException ignore) {
} finally {
w.unlock();
}
}
if (onlyOne)
break;
}
} finally {
mainLock.unlock();
}
}
//清空队列并返回
private List<Runnable> drainQueue() {
BlockingQueue<Runnable> q = workQueue;
List<Runnable> taskList = new ArrayList<Runnable>();//返回list集合
q.drainTo(taskList);
if (!q.isEmpty()) {
for (Runnable r : q.toArray(new Runnable[0])) {
if (q.remove(r))//移除
taskList.add(r);
}
}
return taskList;
}
//中断所有线程
private void interruptWorkers() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (Worker w : workers)
w.interruptIfStarted();
} finally {
mainLock.unlock();
}
}
四、总结
线程池的设计非常的好,更重要的是理解其中的设计思想和原理。