文章目录
线程池
线程池参数
Creates a new ThreadPoolExecutor with the given initial parameters.
Params:
corePoolSize – the number of threads to keep in the pool, even if they are idle, unless allowCoreThreadTimeOut is set
maximumPoolSize – the maximum number of threads to allow in the pool
keepAliveTime – when the number of threads is greater than the core, this is the maximum time that excess idle threads will wait for new tasks before terminating.
unit – the time unit for the keepAliveTime argument
workQueue – the queue to use for holding tasks before they are executed. This queue will hold only the Runnable tasks submitted by the execute method.
threadFactory – the factory to use when the executor creates a new thread
handler – the handler to use when execution is blocked because the thread bounds and queue capacities are reached
Throws:
IllegalArgumentException – if one of the following holds: corePoolSize < 0 keepAliveTime < 0 maximumPoolSize <= 0 maximumPoolSize < corePoolSize
NullPointerException – if workQueue or threadFactory or handler is null
- corePoolSize:线程池中永远不终止的线程,几遍线程内没有任务
- maximumPoolSize:线程池中的最大线程数量
- keepAliveTime :当线程数大于核心线程数时,多余的空闲线程多久终止
- unit :keepAliveTime 的单位
- workQueue :存放执行前的任务,只会存放通过execute方法提交的runnable任务
- threadFactory :线程工厂,用于创建新的线程
- handler :当queue满了的时候的处理器,有四种RejectedExecutionHandler的子类对应着四种拒绝策略
四种拒绝策略
-
AbortPolicy抛异常(默认策略)
public static class AbortPolicy implements RejectedExecutionHandler { /** * Creates an {@code AbortPolicy}. */ public AbortPolicy() { } /** * Always throws RejectedExecutionException. * * @param r the runnable task requested to be executed * @param e the executor attempting to execute this task * @throws RejectedExecutionException always */ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { throw new RejectedExecutionException("Task " + r.toString() + " rejected from " + e.toString()); } }
-
DiscardPolicy,直接无视
/** * Does nothing, which has the effect of discarding task r. */ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { }
-
DiscardOldestPolicy,扔掉最早的任务,执行新任务
/** * Obtains and ignores the next task that the executor * would otherwise execute, if one is immediately available, * and then retries execution of task r, unless the executor * is shut down, in which case task r is instead discarded. */ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { if (!e.isShutdown()) { e.getQueue().poll(); e.execute(r); } }
-
CallerRunsPolicy,使用当前线程执行任务
/** * Executes task r in the caller's thread, unless the executor * has been shut down, in which case the task is discarded. */ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { if (!e.isShutdown()) { r.run(); } }
线程池的五种状态(待补充)
- running
- shutdown
- stop
- tidying
- terminated
线程池execute相关方法源码浅析
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();
// 线程数 < 核心线程数
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true)) // 添加新的核心线程
return;
c = ctl.get(); // 可能由多线程同时执行execute()方法,其他线程率先创建了足够的核心线程,那么后续按照核心线程已满执行
}
// 核心线程已足够
if (isRunning(c) && workQueue.offer(command)) { // 线程池还在running状态,且队列不满(阻塞队列的呃offer()方法会在队列满时返回false)
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false)) // 队列满会尝试添加新线程,直至超过maximumPoolSize
reject(command); // 执行对应的拒绝策略(默认为抛异常)
}
addWorker()——worker初始化(可以简单理解为线程初始化?)
private boolean addWorker(Runnable firstTask, boolean core) { // 参数:firstTask:要执行的Runnable任务, core是否为核心线程
retry:
for (;;) {
int c = ctl.get();
int rs = runStateOf(c); // 线程池状态
// Check if queue empty only if necessary.
if (rs >= SHUTDOWN && // 非 running && (不是shutdown || 任务 != null || queue为空)
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
for (;;) {
int wc = workerCountOf(c); // 线程数
if (wc >= CAPACITY || // 是否超过设定上限
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
if (compareAndIncrementWorkerCount(c)) // CAS增加线程个数,这里改变的是字段ctl
break retry;
c = ctl.get(); // Re-read ctl
if (runStateOf(c) != rs)
continue retry;
// else CAS failed due to workerCount change; retry inner loop
}
}
// CAS成功
boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
try {
w = new Worker(firstTask);
final Thread t = w.thread; // 该worker的线程
if (t != null) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock(); // 加锁
try {
// Recheck while holding lock.
// Back out on ThreadFactory failure or if
// shut down before lock acquired.
int rs = runStateOf(ctl.get());
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) // 更新(似乎不太重要,只是个供我们get的参数)
largestPoolSize = s;
workerAdded = true;
}
} finally {
mainLock.unlock(); // 解锁
}
if (workerAdded) {
t.start(); // runWorker()方法,其中会执行初始任务,并继续从queue获取任务
workerStarted = true;
}
}
} finally {
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
// worker
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this); //通过线程池参数之一的threadFactory创建线程
}
// workers
private final HashSet<Worker> workers = new HashSet<Worker>();
runWorker()——每个线程时如何执行queue里的任务的
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
while (task != null || (task = getTask()) != null) {
w.lock();
// If pool is stopping, ensure thread is interrupted;
// if not, ensure thread is not interrupted. This
// requires a recheck in second case to deal with
// shutdownNow race while clearing interrupt
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; // 任务为null,且queue也没有拿到任务
} finally {
processWorkerExit(w, completedAbruptly); //
}
}
getTask()——keepAliveTime参数时如何运作的
private Runnable getTask() {
boolean timedOut = false; // Did the last poll() time out?
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// Check if queue empty only if necessary.
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
decrementWorkerCount();
return null;
}
int wc = workerCountOf(c);
// Are workers subject to culling?
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize; // core线程是否会过期 || 当前线程数 > corePoolSize,那么需要对corePoolSize以外的线程如果在keepAliveTime的时间内没有拿到任务,那么就要销毁线程 // 所以time表示的是是否要执行过期策略
if ((wc > maximumPoolSize || (timed && timedOut)) // 给超时的空闲线程第二次机会
&& (wc > 1 || workQueue.isEmpty())) {
if (compareAndDecrementWorkerCount(c))
return null;
continue;
}
try {
Runnable r = timed ? // 是否执行过期策略?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : // 过期:keepAliveTime时间内拿不到就设置timedOut = true;会在上面的代码中进行二次拯救,如果届时queue里还是没有任务,worker就被销毁
workQueue.take(); // 不过期:阻塞直至拿到
if (r != null)
return r;
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}