概述
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;
}
ThreadPoolExecutor核心参数简介:
- corePoolSize:核心线程数
- maximumPoolSize:最大线程数
- keepAliveTime:线程存活时间
- unit:线程存活时间的时间单位
- workQueue:阻塞队列
- threadFactory:线程工厂
- handler:拒绝策略
ThreadPoolExecutor核心参数执行作用(重点+常见问题):
当线程数小于核心线程数(corePoolSize)时,通过线程工厂(threadFactory)创建线程并执行任务。
当线程数大于等于核心线程数(corePoolSize)且阻塞队列(workQueue)未满时,将任务放入阻塞队列中等待执行。
当线程数大于等于核心线程数(corePoolSize)、阻塞队列(workQueue)已满并且线程数小于最大线程数(maximumPoolSize)时,创建线程并执行任务。
当线程数大于最大线程数(maximumPoolSize)时,触发拒绝策略(handler)。
源码解析(jdk1.6):
public class ThreadPoolExecutor extends AbstractExecutorService {
//执行任务时的入口
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
//addIfUnderCorePoolSize线程数小于核心线程数时执行该方法
if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) {
//调用队列的offer方法将任务插入队列,若队列已满则返回false
if (runState == RUNNING && workQueue.offer(command)) {
if (runState != RUNNING || poolSize == 0)
ensureQueuedTaskHandled(command);
}
//addIfUnderMaximumPoolSize线程数大于核心线程、小于最大线程并且阻塞队列已满
else if (!addIfUnderMaximumPoolSize(command))
//如果线程数大于最大核心线程数时执行拒绝策略
reject(command); // is shutdown or saturated
}
}
private boolean addIfUnderCorePoolSize(Runnable firstTask) {
Thread t = null;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
//线程数小于核心线程数时执行该方法
if (poolSize < corePoolSize && runState == RUNNING)
t = addThread(firstTask);//创建线程并执行封装好的任务
} finally {
mainLock.unlock();
}
return t != null;
}
private boolean addIfUnderMaximumPoolSize(Runnable firstTask) {
Thread t = null;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
//线程数大于核心线程、小于最大线程并且阻塞队列已满
if (poolSize < maximumPoolSize && runState == RUNNING)
t = addThread(firstTask);
} finally {
mainLock.unlock();
}
return t != null;
}
//拒绝策略
void reject(Runnable command) {
//调用接口方法
handler.rejectedExecution(command, this);
}
}
常见的阻塞队列有哪些?
- ArrayBlockingQueue:数组实现的有界阻塞队列。
- LinkedBlockingQueue:链表实现的无界阻塞队列。
- PriorityBlockingQueue:数组实现的无界且优先排序的阻塞队列。
拒绝策略有哪些?
- AborPolicy : 直接抛出异常。默认策略。
- CallerRunsPolicy : 用调用者所在的线程来执行。
- DiscardOldesPolicy ; 丢弃阻塞队列中最前的任务,并执行当前任务。
- DiscardPolicy : 直接丢弃任务。
- 自定义:实现RejectedExecutionHandler接口。
核心线程(corePoolSize)在执行完任务后会被怎么处理?
结合代码讲解~~~,创建线程并执行任务的主要方法:addThread(runnable)
private Thread addThread(Runnable firstTask) {
Worker w = new Worker(firstTask);
Thread t = threadFactory.newThread(w);
boolean workerStarted = false;
if (t != null) {
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
w.thread = t;
workers.add(w);
int nt = ++poolSize;
if (nt > largestPoolSize)
largestPoolSize = nt;
try {
t.start();
workerStarted = true;
}
finally {
if (!workerStarted)
workers.remove(w);
}
}
return t;
}
从代码中可以开到最终将任务封装成Worker对象,而Worker类实现了Runnable接口所有其本身也可以让线程执行。
直接上Worker类的主要方法~~~
private final class Worker implements Runnable {
/**
* 线程启动时调用的run方法
*/
public void run() {
try {
hasRun = true;
Runnable task = firstTask;
firstTask = null;
//task != null 判定用来执行当前任务,task = getTask()) != null用来执行队列中的任务等等
while (task != null || (task = getTask()) != null) {
//执行任务
runTask(task);
task = null;
}
} finally {
workerDone(this);
}
}
}
到这里还是没有说的重点啊~~~不要急重点就在getTask()方法中~~~
Runnable getTask() {
for (;;) {
try {
int state = runState;
if (state > SHUTDOWN)
return null;
Runnable r;
if (state == SHUTDOWN) // Help drain queue
r = workQueue.poll();
//poolSize > corePoolSize表示非核心线程进行销毁,allowCoreThreadTimeOut主要用来判定核心线程是否可以销毁,可设置
else if (poolSize > corePoolSize || allowCoreThreadTimeOut)
//keepAliveTime线程存活时间,从队列中拿任务时,若队列为空则在keepAliveTime时间内阻塞线程
r = workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS);
else
//若队列为空时阻塞核心线程,等待添加任务
r = workQueue.take();
if (r != null)
return r;
if (workerCanExit()) {
if (runState >= SHUTDOWN) // Wake up others
interruptIdleWorkers();
return null;
}
// Else retry
} catch (InterruptedException ie) {
// On interruption, re-check runState
}
}
}
问题总结:核心线程在执行完任务后会到阻塞队列中获取任务进行执行,若队列中没有任务则挂起线程等待任务,若将allowCoreThreadTimeOut属性设置为true则在等待超时后销毁线程。
非核心线程在执行完任务后会被怎么处理?
源码就不在粘贴了,查看上面的代码吧~~~
非核心线程执行完任务后也会到阻塞队列中获取任务执行,若没有任务根据存活时间(keepAliveTime)等待超时候销毁线程。
最后
以上就是无奈眼睛为你收集整理的线程池讲解之ThreadPoolExecutor的全部内容,希望文章能够帮你解决线程池讲解之ThreadPoolExecutor所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复