1.简介
ThreadPoolExecutor是JUC包下的线程池类,同样Spring包下也有一个ThreadPoolTaskExecutor,主要是对ThreadPoolExecutor的包装,增加回调方法以及增加bean化管理等相关功能,其核心依旧是ThreadPoolExecutor,本文只讨论ThreadPoolExecutor.
2.类信息
2.1 继承关系
ThreadPoolExecutor继承自AbstractExecutorService,很熟悉的模板方法类,子类重写了很多模板方法,但
submit()方法是完全继承AbstractExecutorService的.
2.2 静态变量
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); //原子操作,初始状态为running,工作线程数量为0
private static final int COUNT_BITS = Integer.SIZE - 3; //用于移位
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
// runState is stored in the high-order bits
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; // 所有任务完成,即将调用ternaminated()
private static final int TERMINATED = 3 << COUNT_BITS; // ternaminated()调用完成
//RUNNING: 11100000 00000000 00000000 00000000
//SHUTDOWN: 00000000 00000000 00000000 00000000
//STOP: 00100000 00000000 00000000 00000000
//TIDYING: 01000000 00000000 00000000 00000000
//TERMINATED: 01100000 00000000 00000000 00000000
private static int ctlOf(int rs, int wc) { return rs | wc; }
ctl一个属性就代表了线程池状态+工作线程数, 用一个int字段表示两个字段,类似于ReentrantReadWriteLock中使用一个int表示读锁和写锁的个数.
为啥用一个属性来表示?? 直接两个变量不是更好更清楚?系统缺这么点内存空间?? 好处嘛当然有,当同时需要改变两个字段时,可以避免加锁(因为两个字段需要同步原子化修改),直接用一个运算就可以完成了
2.3 成员变量
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(); //terminate同步状态
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; //最大线程数
2.4 内部类
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;
/**
* Creates with given first task and thread from ThreadFactory.
* @param firstTask the first task (null if none)
*/
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}
/** Delegates main run loop to outer runWorker */
public void run() {
runWorker(this);
}
// Lock methods
//
// The value 0 represents the unlocked state.
// The value 1 represents the locked state.
protected boolean isHeldExclusively() {
return getState() != 0;
}
protected boolean tryAcquire(int unused) {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
protected boolean tryRelease(int unused) {
setExclusiveOwnerThread(null);
setState(0);
return true;
}
public void lock() { acquire(1); }
public boolean tryLock() { return tryAcquire(1); }
public void unlock() { release(1); }
public boolean isLocked() { return isHeldExclusively(); }
void interruptIfStarted() {
Thread t;
if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
try {
t.interrupt();
} catch (SecurityException ignore) {
}
}
}
}