每次新开线程去执行任务,运行完任务销毁线程,都会消耗资源(操作系统级别的线程)
线程池就可以提前创建线程、保留线程,节约资源、节省掉开辟线程和销毁线程的消耗、提高效率
线程池的五种状态,源码注释:
/**
* The runState provides the main lifecycle control, taking on values:
*
* RUNNING: Accept new tasks and process queued tasks
* SHUTDOWN: Don't accept new tasks, but process queued tasks
* STOP: Don't accept new tasks, don't process queued tasks,
* and interrupt in-progress tasks
* TIDYING: All tasks have terminated, workerCount is zero,
* the thread transitioning to state TIDYING
* will run the terminated() hook method
* TERMINATED: terminated() has completed
*/
注意几种状态的区别:
状态 | 会接受新任务 | 会处理队列中任务 | 说明 |
---|---|---|---|
RUNNING | 会 | 会 | 运行态,包括RUNNING和RUNNABLE |
SHUTDOWN | 不会 | 会 | 调用shutdown()方法,设置为这个状态 |
STOP | 不会 | 不会 | 调用shutdownNow()方法,设置该状态 注意:会中断在处理的任务 (一个任务能不能被中断得看任务本身) |
TIDYING | 不会 | 不会 | 所有线程都停掉以后,变成这个状态 最后一个线程退出时,CAS成功设置该状态 最后一个线程判断依据:workCount为0 |
TERMINATED | 不会 | 不会 | TIDYING状态的线程,会调用terminated()方法 执行terminated()方法后,变成该状态 |
注意:线程池调用shutdown()和shutdownNow()方法后,线程不会马上关闭,而是执行完任务后再关闭。
部分源码分析:
// 线程正常退出和异常退出,最终都会执行ThreadPoolExecutor#processWorkerExit方法
// processWorkerExit方法的内部调用ThreadPoolExecutor#tryTerminate方法
// tryTerminate方法中的workerCountOf为线程计数器。正常和异常退出的情况workerCount都会减一
// 正常退出:ThreadPoolExecutor#getTask方法调用compareAndDecrementWorkerCount方法
// 异常退出:ThreadPoolExecutor#processWorkerExit方法调用decrementWorkerCount方法
// 上面的compareAndDecrementWorkerCount和decrementWorkerCount都会对workerCount减一
// ThreadPoolExecutor#tryTerminate
final void tryTerminate() {
for (;;) {
int c = ctl.get();
if (isRunning(c) ||
runStateAtLeast(c, TIDYING) ||
(runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
return;
if (workerCountOf(c) != 0) { // Eligible to terminate,关键,等于0表示最后一个线程
interruptIdleWorkers(ONLY_ONE);
return;
}
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {// TIDYING状态
try {
terminated();// 调用terminated方法后。变为TERMINATED状态
} finally {
ctl.set(ctlOf(TERMINATED, 0));// TERMINATED状态
termination.signalAll();
}
return;
}
} finally {
mainLock.unlock();
}
// else retry on failed CAS
}
}
线程池状态的表示方法:
/**
* The numerical order among these values matters, to allow
* ordered comparisons. The runState monotonically increases over
* time, but need not hit each state. The transitions are:
*
* RUNNING -> SHUTDOWN
* On invocation of shutdown(), perhaps implicitly in finalize()
* (RUNNING or SHUTDOWN) -> STOP
* On invocation of shutdownNow()
* SHUTDOWN -> TIDYING
* When both queue and pool are empty
* STOP -> TIDYING
* When pool is empty
* TIDYING -> TERMINATED
* When the terminated() hook method has completed
*/
// Integer类型是4个字节,也就是32位。因为线程池有5种状态,所以需要3位来表示状态
// 高3位用来表示线程池的状态,剩余的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;
// Packing and unpacking ctl
private static int runStateOf(int c) { return c & ~CAPACITY; }
private static int workerCountOf(int c) { return c & CAPACITY; } // 当前线程的个数
private static int ctlOf(int rs, int wc) { return rs | wc; }
开启线程源码分析:(需要根据状态判断是否需要新开一个线程)
// ThreadPoolExecutor#execute
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;
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
}
}
// 假设核心线程数是10,已有线程数9,这个时候有两个任务进来,结果是一个创建线程一个入队
// 上面的compareAndIncrementWorkerCount成功,会创建一个新的线程执行任务
boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
try {
w = new Worker(firstTask);
final Thread t = w.thread;
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)
largestPoolSize = s;
workerAdded = true;
}
} finally {
mainLock.unlock();
}
if (workerAdded) {
t.start();
workerStarted = true;
}
}
} finally {
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
ThreadPoolExecutor#execute
方法源码:
/**
* Executes the given task sometime in the future. The task
* may execute in a new thread or in an existing pooled thread.
*
* If the task cannot be submitted for execution, either because this
* executor has been shutdown or because its capacity has been reached,
* the task is handled by the current {@code RejectedExecutionHandler}.
*
* @param command the task to execute
* @throws RejectedExecutionException at discretion of
* {@code RejectedExecutionHandler}, if the task
* cannot be accepted for execution
* @throws NullPointerException if {@code command} is null
*/
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) { //小于核心线程数创建线程。并发CAS成功创建,失败入队
if (addWorker(command, true))
return;
c = ctl.get();
}
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);
}
else if (!addWorker(command, false)) //入队失败,创建线程直到最大线程数,或拒绝
reject(command);
}
shutdown方法(中断空闲的线程)
// ThreadPoolExecutor#shutdown
public void shutdown() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
advanceRunState(SHUTDOWN);
interruptIdleWorkers();
onShutdown(); // hook for ScheduledThreadPoolExecutor
} finally {
mainLock.unlock();
}
tryTerminate();
}
// ThreadPoolExecutor#interruptIdleWorkers
private void interruptIdleWorkers() {
interruptIdleWorkers(false);
}
// ThreadPoolExecutor#interruptIdleWorkers,onlyOne is false
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();
}
}
shutdownNow方法(中断所有的线程)
// ThreadPoolExecutor#shutdownNow
public List shutdownNow() {
List tasks;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
advanceRunState(STOP);
interruptWorkers();
tasks = drainQueue();
} finally {
mainLock.unlock();
}
tryTerminate();
return tasks;
}
// ThreadPoolExecutor#interruptWorkers
private void interruptWorkers() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (Worker w : workers)
w.interruptIfStarted();
} finally {
mainLock.unlock();
}
}
// ThreadPoolExecutor#Worker#interruptIfStarted
void interruptIfStarted() {
Thread t;
if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
try {
t.interrupt();
} catch (SecurityException ignore) {
}
}
}
mainLock
全局锁,用到Workers的地方添加这把锁。保证操作的原子性,不发生幻读