以上基于源码自己理解,有不对的地方忘各位赐教
-
jdk 线程池源码解析(基于jdk1.8)
线程池状态
RUNNING:线程池处于运行状态,可以正常提交任务。
SHUTDOWN:不在接收新的任务,会把已运行的线程和队列里存在的线程运行完毕(调用ExecutorService.shutdown())
STOP:不在接收新的任务,且不运行队里里的任务 ,现有已在运行的任务也尝试取消(调用ExecutorService.shutdownnow())
TIDYING:队列里已为空,且没有再运行的任务,但线程池的钩子函数terminated()未执行或者未执行完
TERMINATED:钩子函数terminated()已执行完
图1-1
主要核心参数介绍
1.corePoolSize
解释:线程池最小核心数,如果低于此值,每提交一个任务都会创建一个线程
2.maximumPoolSize
解释:当核心数大于corePoolSize且小于maximumPoolSize 如果放工作队列的任务已满则利用线程工厂创建一个新的线程
3.keepAliveTime
解释:如果allowCoreThreadTimeOut 为false(默认为false),且核心数大于corePoolSize且空闲时间大于keepAliveTime 则进行回收
4.TimeUnit
5.workQueue
解释:存放work的队列
主要以下三个实现
无界队列
有界队列
SynchronousQueue(这个不算是个队列,他没有内存存放任务,只是把提交的任务转发给线程池里的线程)
6.ThreadFactory
解释:创建线程的工厂,每创建一个线程都会调用ThreadFactory.newThread
这个默认是创建一个非守护线程的,正常线程优先级的线程
7.RejectedExecutionHandler
解释:如果现场池coresize数量等于maximumPoolSize,且放置任务的队列已满
则提交任务会有执行拒绝策略。jdk提空了如下策略
ThreadPoolExecutor.AbortPolicy(抛出RejectedExecutionException)
ThreadPoolExecutor.CallerRunsPolicy(直接在主线程执行,阻塞客户端)
ThreadPoolExecutor.DiscardPolicy(直接抛弃,但是不抛异常)
ThreadPoolExecutor.DiscardOldestPolicy(置换最老的任务)
如果以上不符合需求可以实现RejectedExecutionHandler 接口
源码解析
一.类结构分析
1. ThreadPoolExecutor extends AbstractExecutorService
2. AbstractExecutorService implements ExecutorService
3.interface ExecutorService extends Executor
Executor: 只有一个方法(此接口标志这个是个任务执行框架)
ExecutorService :此接口增加了线程生命周期的管理
AbstractExecutorService (骨架实现类主要是对接口的一些默认实现)
ThreadPoolExecutor(实现的一个线程池的执行服务,生命周期管理,线程创建)
二.任务执行流程
三.小技巧
ThreadPoolExecutor 利用一个int表示两个状态
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
正在运行的核心数
线程池的状态
一个int是32为,将其拆分为前3位和后29位
前三位表示线程池状态,后29位表示运行的核心数
即111(后29为表示正在运行的核心数)表示可运行,
即000(后29为表示正在运行的核心数)表示shutdown,
即001(后29为表示正在运行的核心数)表示STOP,
即010(后29为表示正在运行的核心数)表示TIDYING,
即011(后29为表示正在运行的核心数)表示TERMINATED,
即小于0表示可运行状态
四.threadPoolExecutor.execute源码解析
1.execute 方法
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
//存放实际运行核心数和线程池状态的原子变量
int c = ctl.get();
/**
* 判断实际执行线程是否小于corePoolSize 如果小于
* 则执行addWorker(addWorker 创建新的线程执行任务)
* 如果addwork执行成功则直接返回
* 如果不成功则表示有其他任务并发的调用addWorker()
* 走下面的逻辑(下面的逻辑后面分析)
*/
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
2.addwork分析
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {
//获取存放状态变量和运行数量的原子变量
int c = ctl.get();
int rs = runStateOf(c);
/**
* 由前面的小技巧知道 >=SHUTDOWN 除了running为负数其他的状态都是大于等于SHUTDOWN
* ! (rs == SHUTDOWN &&
* firstTask == null &&
* ! workQueue.isEmpty())
* 这个判断个人理解(我们知道线程池处于SHUTDOWN 状态,需要执行完所有的队列里的任务,
* 如果这个队列比较大且我们想尽快执行完队列里的任务,我们可以适当增加核心数(setcoresize),
* 然后调用prestartAllCoreThreads(会调用addWorker(null,true))产生更多的core,以便更快的消费队列里的任务)
*
*/
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
for (;;) {
//获取活动线程数
int wc = workerCountOf(c);
/**
* CAPACITY 活动线程的最大表示法(即int的后39为所能表示的最大值)
* 如果有其他线程并发修改了此值是的core大于等于了corePoolSize则返回false
*
*/
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
//通过cas 修改实际运行的值如果修改成功则跳出循环
if (compareAndIncrementWorkerCount(c))
break retry;
c = ctl.get();
//如果线程池状态改变跳到上一个循环重新执行
if (runStateOf(c) != rs)
continue retry;
// else CAS failed due to workerCount change; retry inner loop
}
}
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());
//rs < SHUTDOWN 如果线程池处于运行状态 (rs == SHUTDOWN && firstTask == null)) 这个是上面判断的反面
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
// 判断线程是否或者
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
//将活动线程放在维护的set中
workers.add(w);
int s = workers.size();
// 全局变量维护着最大的活动线程
if (s > largestPoolSize)
largestPoolSize = s;
workerAdded = true;
}
} finally {
mainLock.unlock();
}
if (workerAdded) {
//执行线程的start方法启动线程
t.start();
workerStarted = true;
}
}
} finally {
//失败处理
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
3.Worker线程类分析
//构造函数 setState 表示线程已创建但未开始执行start
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}
//进一步查看runWorker
public void run() {
runWorker(this);
}
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();
// 如果当前线程池状态大于等于stop 则保持线程处于中断状态
//防止线程无线阻塞停止不了 合理的终止线程
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);
}
}
4.getTask() 方法分析
boolean timedOut = false;
for (;;) {
// 存放线程池状态及核心说的变量
int c = ctl.get();
int rs = runStateOf(c);
// Check if queue empty only if necessary.
//如果线程池状态为大于shutdown 线程池队列为空,或者状态大于stop 则直接返回null 让线程结束
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
decrementWorkerCount();
return null;
}
// 核心数
int wc = workerCountOf(c);
// 如果allowCoreThreadTimeOut false(如果不想回收线程可以设置这个参数为true) 并且 活动线程数> corePoolSize
// 说明需要进行回收
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
//如果wc 大于最大线程数,或者线程空闲时间超时 (timedOut 为true) 并且队列为空 则返回null 回收线程
if ((wc > maximumPoolSize || (timed && timedOut))
&& (wc > 1 || workQueue.isEmpty())) {
if (compareAndDecrementWorkerCount(c))
return null;
continue;
}
try {
//在活越时间内如果从队里里拿不到线程则设置timedOut ,如果拿到则返回队列里的任务
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
if (r != null)
return r;
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}
六.下面分析execute 后半段代码
//如果线程池是running状态 则将线程放入线程队列
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);
7.其他api的介绍
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null);
execute(ftask);
return ftask;
}
这个方法也是走的execute 只是外围封装了一层
public void shutdown() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
advanceRunState(SHUTDOWN);
interruptIdleWorkers();
onShutdown(); // hook for ScheduledThreadPoolExecutor
} finally {
mainLock.unlock();
}
tryTerminate();
}
这个方法是修改线程状态,将空闲线程设置为中断状态,调用线程onShutdown 的回调函数,尝试进入Terminate
public List<Runnable> shutdownNow() {
List<Runnable> tasks;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
advanceRunState(STOP);
interruptWorkers();
tasks = drainQueue();
} finally {
mainLock.unlock();
}
tryTerminate();
return tasks;
}
public int getActiveCount() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
int n = 0;
for (Worker w : workers)
if (w.isLocked())
++n;
return n;
} finally {
mainLock.unlock();
}
}
public boolean isLocked() { return isHeldExclusively(); }
protected boolean isHeldExclusively() {
return getState() != 0;
}
这个获取已经创建但未调用start的线程
public int prestartAllCoreThreads() {
int n = 0;
while (addWorker(null, true))
++n;
return n;
}
初始化空线程到核心数(这个方法可以让线程池再没有获取任务时就初始化线程)
public boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException {
long nanos = unit.toNanos(timeout);
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (;;) {
if (runStateAtLeast(ctl.get(), TERMINATED))
return true;
if (nanos <= 0)
return false;
nanos = termination.awaitNanos(nanos);
}
} finally {
mainLock.unlock();
}
}
这个方法是等待线程池处于termination 在规定时间内(如果已经是termination 则直接返回true)
public void purge() {
final BlockingQueue<Runnable> q = workQueue;
try {
Iterator<Runnable> it = q.iterator();
while (it.hasNext()) {
Runnable r = it.next();
if (r instanceof Future<?> && ((Future<?>)r).isCancelled())
it.remove();
}
} catch (ConcurrentModificationException fallThrough) {
// Take slow path if we encounter interference during traversal.
// Make copy for traversal and call remove for cancelled entries.
// The slow path is more likely to be O(N*N).
for (Object r : q.toArray())
if (r instanceof Future<?> && ((Future<?>)r).isCancelled())
q.remove(r);
}
tryTerminate(); // In case SHUTDOWN and now empty
}
尝试删除运行队列里的任务
public boolean remove(Runnable task) {
boolean removed = workQueue.remove(task);
tryTerminate(); // In case SHUTDOWN and now empty
return removed;
}
尝试删除任务
其他的方法都是对现有参数的一些设置不列举了
.扩展
1.可以集成ThreadPoolExecutor 重写以下 方法(可以在每个任务执行之前和之后做一些日志记录)
beforeExecute() 每个任务执行之前调用的方法
afterExecute() 每个任务执行之后调用的方法
2.继承ThreadFactory 实现自己的线程工厂
jdk默认实现
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;
}
jdk默认是创建一个非守护线程,线程优先级为NORM_PRIORITY 的线程 默认组
我们可以重写newThread 给创建的线程起一个合理的名字方便查看,建立一些日志信息每创建一个线程时等
3.实现RejectedExecutionHandler 接口 建立自己的处理策略
void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
比如我们可以把不能 处理的任务广播给其他机器处理等