Executor :运行新任务的简单接口,将任务提交和任务执行细节解耦
ExecutorService:具备管理执行器和任务生命周期的方法,提交任务机制更完善
corePoolSize 核心线程池大小
maximumPoolSize 最大线程池大小
线程池会根据corePoolSize和maximumPoolSize自动调整线程池的大小
规则:
1. 当正在执行的线程数量少于corePoolSize的时候,即使存在线程空闲,也会创建一个新的线程来处理新的任务。
2. 如果当前正在运行的线程大于等于corePoolSize但小于maximumPoolSize,且等待队列不满,则将新的任务压入等待队列,否则如果队列已满,则创建新的线程来处理新任务。
3. 如果此时当前正在执行的线程数等于maximumPoolSize,则执行拒绝策略
通过执行流程我们可以得出以下总结:
当设置corePoolSize和maximumPoolSize相同,可以创建一个固定大小的线程池
设置maximumPoolSize为一个极大的值,即创建了一个可以容纳任意数量的并发任务
注意:通常这两个参数仅在构建时设置,但也可以通过set方法动态设置
keepAliveTime 线程最大空闲时间
TimeUnit unit 时间单位
如果线程池当前拥有超过corePoolSize的线程,那么多余的线程在空闲时间超过keepAliveTime时会被终止。这提供了一种在不积极使用线程池时减少资源消耗的方法。
注意:如果池子变得活跃,则可以通过set方法动态调整
keep-alive策略仅适用于存在超过corePoolSize线程的情况。 但是,只要keepAliveTime值不为零,方法allowCoreThreadTimeOut(boolean)
也可用于将此超时策略应用于核心线程。
BlockingQueue 等待队列
BlockingQueu用于存放提交的任务,当队列已满时,则执行拒绝策略
ThreadFactory 线程创建工厂
新线程使用ThreadFactory创建。 如果未另行指定,则使用Executors.defaultThreadFactory默认工厂,使其全部位于同一个ThreadGroup中,并且具有相同的NORM_PRIORITY优先级和非守护进程状态。
通过提供不同的ThreadFactory,您可以更改线程的名称,线程组,优先级,守护进程状态等。
RejectedExecutionHandler 拒绝策略
拒绝任务有两种情况:1. 线程池已经被关闭;2. 任务队列已满且maximumPoolSizes已满;
重要方法:
在默认情况下,只有当新任务到达时,才开始创建和启动核心线程,但是我们可以使用 prestartCoreThread()
和 prestartAllCoreThreads()
方法动态调整。
如果使用非空队列构建池,则可能需要预先启动线程。
ThreadPoolExecutor为提供了每个任务执行前后提供了钩子方法,重写beforeExecute(Thread,Runnable)
和afterExecute(Runnable,Throwable)
方法来操纵执行环境; 例如,重新初始化ThreadLocals,收集统计信息或记录日志等。此外,terminated()
在Executor完全终止后需要完成后会被调用,可以重写此方法,以执行任殊处理。
prestartCoreThread 核心线程预启动
在默认情况下,只有当新任务到达时,才开始创建和启动核心线程,但是我们可以使用 prestartCoreThread()
和 prestartAllCoreThreads()
方法动态调整。
如果使用非空队列构建池,则可能需要预先启动线程。
Hook methods 钩子方法
ThreadPoolExecutor为提供了每个任务执行前后提供了钩子方法,重写beforeExecute(Thread,Runnable)
和afterExecute(Runnable,Throwable)
方法来操纵执行环境; 例如,重新初始化ThreadLocals,收集统计信息或记录日志等。此外,terminated()
在Executor完全终止后需要完成后会被调用,可以重写此方法,以执行任殊处理。
shutdown()方法
shutdownNow()方法
Executors:线程池工厂
ThreadPoolExecutor将线程池的线程的个数与线程池的状态融合到一个int型的整型数中,其中高29位表示线程的数量,低三位表示状态
private final AtomicInteger ctl = new AtomicInteger(ctlOf(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;
private static final int TERMINATED = 3 << COUNT_BITS;
private final HashSet<Worker> workers = new HashSet<Worker>();
Worker是线程的一个内部类,其设计为
private final class Worker extends AbstractQueuedSynchronizer implements Runnable
{
private static final long serialVersionUID = 6138294804551838833L;
final Thread thread;//工作的线程
Runnable firstTask;//初始化时的第一个任务,可能是null
volatile long completedTasks;//线程完成的工作数量
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);//从工厂获取一个线程
}
public void run() {
runWorker(this);//代理,执行的是runWorker{被定义在外部类中}
}
// 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) {
}
}
}
}
ThreadPoolExecutor的父接口定义了多个接口以适应不同的需求
其中包括两大类:
实际上:Callable接口的实现之所以能够实现能获取返回值,是因为Callable接口最终被包装Runnable接口的实现类(FutureTask),因此submit方法实际上仍然是将Callable接口封装为Runnable类,进而交给executor去执行。
//ExecutorService定义了三个提交任务的接口
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);
//ExecutorService的父接口Executor定义的接口
void execute(Runnable command);
实现方法
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
//包装成RunnableFuture(Runnbale子类),实际上就是FutureTask
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);//交给execute执行
return ftask;
}
execute
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
/*
* Proceed in 3 steps:
*
* 1. If fewer than corePoolSize threads are running, try to
* start a new thread with the given command as its first
* task. The call to addWorker atomically checks runState and
* workerCount, and so prevents false alarms that would add
* threads when it shouldn't, by returning false.
*
* 2. If a task can be successfully queued, then we still need
* to double-check whether we should have added a thread
* (because existing ones died since last checking) or that
* the pool shut down since entry into this method. So we
* recheck state and if necessary roll back the enqueuing if
* stopped, or start a new thread if there are none.
*
* 3. If we cannot queue task, then we try to add a new
* thread. If it fails, we know we are shut down or saturated
* and so reject the task.
*/
int c = ctl.get();
//1. 如果少于核心线程数,则会尝试 创建新的线程,并将此任务当作第一个任务;addWorker的调用以原子方式不断检查runState和workercount,并通过返回false来防止在不应该添加线程时产生的假警报。
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();//当线程数量达到了阈值,则addWorker返回false,进行下面的处理
/*
下面的处理存在两种情况:
1.添加到任务队列
2.尝试创建>核心线程数的线程
*/
}
//如果正在运行 则将任务提交到工作队列中;如果成功入队,则进行第二次检擦
//检查是否应该添加一个线程(因为现有线程在Last检查之后已经死亡),或者池在进入该方法后关闭。因此,我们重新检查状态,如果有必要,则在停止排队时回滚排队;如果没有线程,则启动一个新线程。
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))//如果在检查时,发现池子已经不运行了,回滚排队
reject(command);//拒绝
else if (workerCountOf(recheck) == 0)
addWorker(null, false);//仍在在运行,但是没有线程了(可能是考虑核心线程数为0的情况),则启动一个新线程。
}
//3.如果没有正在运行或者工作队列已经满了无法提交新的任务,则ch尝试创建新的worker来执行线程。
else if (!addWorker(command, false))
reject(command);
}
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 &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
for (;;) {
int wc = workerCountOf(c);//线程数量
if (wc >= CAPACITY || //线程数大于最大容量或者大于等于核心线程数
wc >= (core ? corePoolSize : maximumPoolSize))
return false;//在core的情况,如果超过限度则返回false,表示不能继续添加
if (compareAndIncrementWorkerCount(c))
break retry;//增加 线程数量 成功退出
c = ctl.get(); // 失败则重新获取state
if (runStateOf(c) != rs)//如果state发生了改变,则进行下一次循环
continue retry;
}
}
//如果程序来到这,说明此时任务已经获得了创建新线程并执行任务的资格。
boolean workerStarted = false;//任务线程是否已经开始执行任务
boolean workerAdded = false;//线程是否已经被添加到线程池
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 {
int rs = runStateOf(ctl.get());
if (rs < SHUTDOWN ||//线程池子处于运行状态
(rs == SHUTDOWN && firstTask == null)) {//线程池虽然处于Shutdown状态,但是firsttask为null。说明存在任务在shutdown之前提交到了queue,但是已经没有线程执行了,则可以在此处创建一个新的线程去执行
if (t.isAlive())
throw new IllegalThreadStateException();
workers.add(w);//将worker加入到线程池中
int s = workers.size();
if (s > largestPoolSize)//largestPoolSize 跟踪最大达到的池大小。仅在mainLock下访问。
largestPoolSize = s;
workerAdded = true;
}
} finally {
mainLock.unlock();
}
if (workerAdded) {
t.start();//启动线程
workerStarted = true;
}
}
} finally {
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
//如果任务不为null,则执行任务
//否则 获取任务
while (task != null || (task = getTask()) != null) {
w.lock();
// 如果池子被停止,则确保线程被打断;如果没有,则确保线程不被打断;这需要一个重新检查,第二次是为了当清除打断之后来处理shutdownNow方法
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() &&
runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
wt.interrupt();
try {
beforeExecute(wt, task);
Throwable thrown = null;
try {
task.run();//执行任务
} 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 {
processWorkerExit(w, completedAbruptly);
}
}
private Runnable getTask() {
boolean timedOut = false; // Did the last poll() time out?
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
//只在必要时检查队列是否为空。
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
decrementWorkerCount();//清除所有的worker
return null;
}
int wc = workerCountOf(c);
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
if ((wc > maximumPoolSize || (timed && timedOut))
&& (wc > 1 || workQueue.isEmpty())) {
if (compareAndDecrementWorkerCount(c))
return null;
continue;
}
try {
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();//获取任务
if (r != null)
return r;
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}