线程池讲解
创建线程池的几种方式:
- Executors.newCachedThreadPool();
- Executors.newFixedThreadPool(3);
- Executors.newSingleThreadExecutor();
- Executors.newScheduledThreadPool(5);
我们发现上面的静态方法创建线程池都会调用以下的ThreadPoolExecutor的构造方法来创建
一、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.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
先解释下构造方法的几个参数的意思:
- corePoolSize,在线程池里面保持的线程数量,即使线程池是空闲的它也不会回收,除非设置allowCoreThreadTimeOut
- maximumPoolSize,允许线程池里面最大存在线程的数量
- keepAliveTime,当线程超出核心线程(corePoolSize)的数量时,这个是闲置线程等待新线程到来的最大时间
- unit,是keepAliveTime时间的单位(毫秒、秒、分)
- workQueue,用于在执行任务之前使用的队列。此队列只保存 execute方法提交的Runnable任务。
- threadFactory,当Executor 创建新线程时使用的工厂
- handler,在执行被阻塞时使用的处理程序,因为到达了线程边界和队列容量
在线程池创建完后,我们会调用方法执行
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(new Runnable() {
@Override
public void run() {
}
});
ExecutorService 是一个接口,真正调用的是ThreadPoolExecutor的execute方法,下面我们看下execute方法
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
/*
* Proceed in 3 steps:
*
* 1. 如果小于corePoolSize的线程正在运行,会以给定的命令启动一个新线程作为它的第一个任
* 务。对addWorker的调用会对runState和workerCount进行原子检查,因此可以防止错误警报在不
* 应该的情况下添加线程
*
* 2.如果一个任务可以成功地排队,那么我们仍然需要再次检查是否应该添加一个线程(因为现有的线
* 程在上次检查后死亡),或者是在该方法进入后关闭了池。因此,我们需重新检查状态,如果不是
* Running有必要回滚队列,或如果没有线程则启动一个新线程。
*
* 3. 如果我们不能排队任务,那么我们尝试添加一个新线程。如果失败了,我们知道我们已经被关闭
* 或饱和,所以拒绝这个任务。
*/
// 获取携带了线程池运行状态及线程数量的int值(前3位statue后29位代表数量)
int c = ctl.get();
// 如果线程数小于核心线程数则新建线程不执行下面的if语句后面的语句
if (workerCountOf(c) < corePoolSize) {
// 源码解释在下面
if (addWorker(command, true))
return;
c = ctl.get();
}
// 下面代码的解释请看上面的第二、第三步
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
// 拒接task
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false))
reject(command);
}
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
/* 线程池是其他状态,及如果线程池不是SHUTDOWN状态或者firstTask不为空或者workQueu
*为空返回false
*/
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
}
}
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;
}
看下worker对象的构造方法
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}
使用线程工厂创建线程,我们来看下默认的线程工厂模式
/**
* The default thread factory.
*/
private 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-";
}
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;
}
}
从上面的Worker的构造方法里面创建线程的时候携带了Worker对象,这样t.start()最后调用的是Worker对象的run方法
private final class Worker
extends AbstractQueuedSynchronizer
implements Runnable
{
`````````
public void run() {
runWorker(this);
}
`````````
}
下面卡看下runWorker方法
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;
} finally {
processWorkerExit(w, completedAbruptly);
}
}
最后是取任务
private Runnable getTask() {
boolean timedOut = false; // Did the last poll() time out?
retry:
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;
}
boolean timed; // Are workers subject to culling?
for (;;) {
int wc = workerCountOf(c);
timed = allowCoreThreadTimeOut || wc > corePoolSize;
if (wc <= maximumPoolSize && ! (timedOut && timed))
break;
if (compareAndDecrementWorkerCount(c))
return null;
c = ctl.get(); // Re-read ctl
if (runStateOf(c) != rs)
continue retry;
// else CAS failed due to workerCount change; retry inner loop
}
try {
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
if (r != null)
return r;
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}