线程状态
线程池中状态说明
1、RUNNING
(1) 状态说明:线程池处在RUNNING状态时,能够接收新任务,以及对已添加的任务进行处理。
(02) 状态切换:线程池的初始化状态是RUNNING。换句话说,线程池被一旦被创建,就处于RUNNING状态,并且线程池中的任务数为0!
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
- 1
2、 SHUTDOWN
(1) 状态说明:线程池处在SHUTDOWN状态时,不接收新任务,但能处理已添加的任务。
(2) 状态切换:调用线程池的shutdown()接口时,线程池由RUNNING -> SHUTDOWN。
3、STOP
(1) 状态说明:线程池处在STOP状态时,不接收新任务,不处理已添加的任务,并且会中断正在处理的任务。
(2) 状态切换:调用线程池的shutdownNow()接口时,线程池由(RUNNING or SHUTDOWN ) -> STOP。
4、TIDYING
(1) 状态说明:当所有的任务已终止,ctl记录的”任务数量”为0,线程池会变为TIDYING状态。当线程池变为TIDYING状态时,会执行钩子函数terminated()。terminated()在ThreadPoolExecutor类中是空的,若用户想在线程池变为TIDYING时,进行相应的处理;可以通过重载terminated()函数来实现。
(2) 状态切换:当线程池在SHUTDOWN状态下,阻塞队列为空并且线程池中执行的任务也为空时,就会由 SHUTDOWN -> TIDYING。
当线程池在STOP状态下,线程池中执行的任务为空时,就会由STOP -> TIDYING。
5、 TERMINATED
(1) 状态说明:线程池彻底终止,就变成TERMINATED状态。
(2) 状态切换:线程池处在TIDYING状态时,执行完terminated()之后,就会由 TIDYING -> TERMINATED。
线程池源码状态
ctl
内部有重要的成员变量ctl,类型是AtomicInteger,低29位表示线程池中线程数,通过高3位表示线程池的运行状态
COUNT_BITS的值是29
1、RUNNING:-1 << COUNT_BITS,即高3位为111,该状态的线程池会接收新任务;
2、SHUTDOWN: 0 << COUNT_BITS,即高3位为000,该状态的线程池不会接收新任务;
3、STOP : 1 << COUNT_BITS,即高3位为001;
4、TIDYING : 2 << COUNT_BITS,即高3位为010, 所有的任务都已经终止;
5、TERMINATED: 3 << COUNT_BITS,即高3位为011, terminated()方法已经执行完成
ThreadPoolExecutor 初始化参数
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.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
defaultThreadFactory 默认工厂工具类
public static ThreadFactory defaultThreadFactory() {
return new DefaultThreadFactory();
}
DefaultThreadFactory 工具类 创建核心线程
static class DefaultThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
DefaultThreadFactory() {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
// 线程名
namePrefix = "pool-" +
poolNumber.getAndIncrement() +
"-thread-";
}
// r 就是封装的worker对象 这个对象实现了runnable接口
// 所以当线程启动的时候回执行worker对象重写的run方法
public Thread newThread(Runnable r) {
// 创建线程
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
// 返回创建的线程
return t;
}
}
execute 执行任务
public void execute(Runnable command)
{
if (command == null)
throw new NullPointerException();
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
//workerCountOf获取线程池的当前线程数;小于corePoolSize,执行addWorker创建新线程执行command任务
if (addWorker(command, true))
return;
c = ctl.get();
}
// double check: c, recheck
// 线程池处于RUNNING状态,把提交的任务成功放入阻塞队列中
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
// recheck and if necessary 回滚到入队操作前,即倘若线程池shutdown状态,就remove(command)
//如果线程池没有RUNNING,成功从阻塞队列中删除任务,执行reject方法处理任务
if (! isRunning(recheck) && remove(command))
reject(command);
//线程池处于running状态,但是没有线程,则创建线程
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
// 往线程池中创建新的线程失败,则reject任务
else if (!addWorker(command, false))
reject(command);
}
讲解
为什么需要double check线程池的状态? 在多线程环境下,线程池的状态时刻在变化,而ctl.get()是非原子操作,很有可能刚获取了线程池状态后线程池状态就改变了。判断是否将command加入workque是线程池之前的状态。倘若没有double check,万一线程池处于非running状态(在多线程环境下很有可能发生),那么command永远不会执行。
addWorker(Runnable firstTask, boolean core) firstTask 任务 core =true
// firstTask 可以为 null ,表示启动worker之后,worker自动到queue中获取,
//如果不是 null ,则worker执行firstTaSK
// core 采用的线程数限制,如果为true 采用核心线程数 限制; false,
//采用 maximumPoolSize 线程数限制
// 返回值总结:
// true: 表示创建worker成功,且线程启动
// false : 表示创建worker失败
// 1.线程池状态rs > SHUTDOWN
// 2. rs == SHUTDOWN 但是队列中已经没有任务了
//或者当前状态是 SHUTDOWN 且队列未空,但是 firstTask不为 null
// 3.当前线程已经达到指定指标(corePoolSize 或者 maximumPoolSize)
// 4.线程池ThreadFactory 创建的线程是 null
private boolean addWorker(Runnable firstTask, boolean core)
{
// 自旋 判断当前线程池状态是否允许创建线程的事情。
retry:
for (;;) {
// 获取当前的 ctl 值
int c = ctl.get();
// 获取当前线程池运行状态
int rs = runStateOf(c);
// Check if queue empty only if necessary.
// 条件一 : rs >= SHUTDOWN true: 表示当前线程池状态不是Running
// 条件二: ! (rs == SHUTDOWN && firstTask == null && ! workQueue.isEmpty())
// true : 当线程池状态, rs > SHUTDOWN 或者 rs == SHUTDOWN 但是队列中已经没有任务了,或者 rs == SHOTDOWN 且 firstTask不为空
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
// 以上代码就是判断当前线程池状态是否允许添加线程
// 内部自旋 ,获取创建线程令牌的过程
for (;;) {
// 获取当前线程池中线程数量
int wc = workerCountOf(c);
// 条件一: wc >= CAPACITY 永远不成立,
//CAPACITY是一个5亿多的数据
// 条件二: wc >= (core ? corePoolSize : maximumPoolSize)
// core == true ,判断当前线程数量是否 >= corePoolSize,
//会拿核心线程数量做限制
// core == false ,判断当前线程数量是否 >= corePoolSize,
会拿最大线程数量做限制
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
// 表明当前无法添加新的线程了。
return false;
// true: 说明记录线程数量已经 +1成功了,相当于申请到了一块令牌。
// false : 说明其他线程修改过了ctl 值了。可能其他线程execute() 申请过令牌了。
if (compareAndIncrementWorkerCount(c))
// cas 成功,申请到令牌了
// 直接跳出了 retry 外部的自旋
break retry;
// 没申请到令牌,再次获取ctl的最新值
c = ctl.get(); // Re-read ctl
// 判断当前线程池状态是否发生过改变,
//如果外部在这之前调//shutDown, shutDown会导致状态发生改变
if (runStateOf(c) != rs)
// 状态发生改变后,返回到外层循环
continue retry;
}
}
// 来到了这里
// 表示创建的worker是否已经启动, false 未启动
boolean workerStarted = false;
// 创建的 worker是否添加到池子中,默认false, 未添加
boolean workerAdded = false;
// 表示 后面创建worker的一个引用
Worker w = null;
try
{
// 创建worker,执行完后,线程创建完毕
w = new Worker(firstTask);
// 将创建的线程节点, 赋值
final Thread t = w.thread;
// 进行了一次判断,为什么要判断?
if (t != null)
{
// 将全局锁的引用保存到 mainLock
final ReentrantLock mainLock = this.mainLock;
// 持有全局锁,可能会阻塞,知道获取成功为止,
//同一时刻,操作线程池内部相关的操作,都必须持有锁
mainLock.lock();
try
{
// 再次去获取最新的ctl 值,即运行状态
int rs = runStateOf(ctl.get());
// 条件一: true: 表示 当前线程池为正常的RUNNING状态
// 条件二: (rs == SHUTDOWN && firstTask == null)
// true: 当前的线程状态为 SHUTDOWN ,且 firstTask 为空
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
// 当线程start后,线程isAlive会返回true ;
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
// 添加到线程池中 就是把创建的线程对象保存到hashSet集合中
workers.add(w);
// 获取最新的 线程池中的worker的数量
int s = workers.size();
// true :说明当前线程数量时一个新高了,更新最大值
if (s > largestPoolSize)
//其实这个值就是记录当前线程池中线程的数量
// 一个worker 对象代表一个线程
largestPoolSize = s;
// 表示线程已经加入到线程池中了
workerAdded = true;
}
} finally {
// 解锁
mainLock.unlock();
}
// 说明当前添加worker添加是成功的
if (workerAdded) {
// 启动线程
// 这里很关键 启动创建的线程 这样的话会执行
// 线程中的run 方法
t.start();
// 启动标记设置为true
workerStarted = true;
}
}
} finally {
// 如果整个条件成立,说明启动失败,需要做清理工作
if (! workerStarted)
// 1.释放令牌
// 2.当前worker 清理出workers 集合
addWorkerFailed(w);
}
// 返回新创建的线程是否启动
return workerStarted;
}
Worker 对象封装了创建的线程对象thread
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;
// 创建的线程
final Thread thread;
//线程要执行的匿名内部类runnable接口 execute方法传入的参数
Runnable firstTask;
volatile long completedTasks;
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
// 线程要执行的匿名内部类runnable接口
this.firstTask = firstTask;
// this 就是创建的worker 对象 这段源码在上面
this.thread = getThreadFactory().newThread(this);
}
/** Delegates main run loop to outer runWorker */
public void run()
{
// 当线程执行start方法的时候 真正执行的是这个方法
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) {
}
}
}
}
runWorker 线程真正执行的方法 封装在run 方法中
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try
{
// 创建的线程为啥不会自己死掉 原因就在getTask方法是阻塞的
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;
} finally {
processWorkerExit(w, completedAbruptly);
}
}
getTask 获取队列中要执行的任务
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;
}
// 跑到这里说明线程池还处于RUNNING状态,重新获取一次工作线程数
int wc = workerCountOf(c);
// Are workers subject to culling?
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;
}
}
}
非核心线程回收逻辑
核心就是上面的代码,其中allowCoreThreadTimeOut默认为false的,wc表示当前线程池中的线程数量,如果数量大于核心线程数,则执行带超时的poll方法,这样一段时间没有任务的话会返回null,然后等待执行的线程就会执行完毕,进而销毁,否则会执行take方法,该方法会一直阻塞,这也就是为什么核心线程会不断存在的原因。
其实并没有核心线程和非核心线程的区分,只是通过数量来判断是否该回收线程,回收的线程就被成为非核心线程,可以设置allowCoreThreadTimeOut为true,这样每个线程在固定的时间内拿不到任务就会被回收。
当超时后,则拿到的任务就是个null,执行销毁逻辑,从hashset中将该work对象移除,