当调用 execute() 方法添加一个任务时,线程池会做如下判断:
a. 如果正在运行的线程数量小于 corePoolSize,那么马上创建线程运行这个任务;
b. 如果正在运行的线程数量大于或等于 corePoolSize,那么将这个任务放入队列。
c. 如果这时候队列满了,而且正在运行的线程数量小于 maximumPoolSize,那么还是要创建线程运行这个任务;
d. 如果队列满了,而且正在运行的线程数量大于或等于 maximumPoolSize,那么线程池会抛出异常,告诉调用者“我不能再接受任务了”。
e.当一个线程完成任务时,它会从队列中取下一个任务来执行。
f.当一个线程无事可做,超过一定的时间(keepAliveTime)时,线程池会判断,如果当前运行的线程数大于 corePoolSize,那么这个线程就被停掉。所以线程池的所有任务完成后,它最终会收缩到 corePoolSize 的大小。
一:Executor 将有限边界用于最大线程和工作队列容量饱和:
ThreadPoolExecutor.AbortPolicy
中,处理程序遭到拒绝将抛出运行时RejectedExecutionException
。ThreadPoolExecutor.CallerRunsPolicy
中,线程调用运行该任务的execute
本身。此策略提供简单的反馈控制机制,能够减缓新任务的提交速度。ThreadPoolExecutor.DiscardPolicy
中,不能执行的任务将被删除,不抛出异常。ThreadPoolExecutor.DiscardOldestPolicy
中,如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,然后重试执行程序(如果再次失败,则重复此过程)。不抛出异常。
public class LufaxThreadFactory implements ThreadFactory {
private static final ThreadFactory DEFAULT_THREAD_FACTORY = Executors.defaultThreadFactory();
public LufaxThreadFactory(String module) {
this.module = module;
}
@Override
public Thread newThread(Runnable r) {
if (r == null) throw new NullPointerException();
Thread t = DEFAULT_THREAD_FACTORY.newThread(r);
//设置捕获异常
t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
Logger.error(this, String.format("Failed to exeute runnable r [module:%s]", module), e);
}
});
return t;
}}
2)executorService.execute(Callable
线程池 java.util.concurrent.ThreadPoolExecutor 会Catch住所有异常, 当任务执行完成(java.util.concurrent.ExecutorService.submit(Callable))获取其结果 时(java.util.concurrent.Future.get())会抛出此RuntimeException。
V innerGet() throws InterruptedException, ExecutionException {
acquireSharedInterruptibly(0);
if (getState() == CANCELLED)
throw new CancellationException();
if (exception != null)
throw new ExecutionException(exception);
return result;
}
三:钩子回调 beforeExecute()和afterExecute() 监控线程
也就是说当我们想线程池 ThreadPoolExecutor(java.util.concurrent.ExecutorService)提交任务时, 如果不理会任务结果(Feture.get()),那么此异常将被线程池吃掉。
privatevolatileint corePoolSize; //都是volatile变量
ExecutorService service = Executors.newFixedThreadPool(3);//底层ThreadPoolExecutor
publicclass ThreadPoolExecutor extends AbstractExecutorService{}
publicstatic ExecutorService newFixedThreadPool(int nThreads) {
returnnew ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue
}
publicvoid execute(Runnable command) {
if (command == null)
thrownew NullPointerException();
//poolSize大于等于corePoolSize时不增加线程,反之(poolSize < corePoolSize)新初始化线程
if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) {
//线程执行状态外为执行,同时可以添加到队列中
if (runState == RUNNING && workQueue.offer(command)) { //入队列
if (runState != RUNNING || poolSize == 0)
ensureQueuedTaskHandled(command);
}
elseif (!addIfUnderMaximumPoolSize(command))//队列已满,并且未达到MaxPoolSize继续启动线程
reject(command); // is shutdown or saturated
}
}
privateboolean 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();
}
if (t == null)
returnfalse;
t.start(); //启动线程
returntrue;
}
private Thread addThread(Runnable firstTask) {
Worker w = new Worker(firstTask); //Worker包装Runnable
Thread t = threadFactory.newThread(w); //生成线程对象Thread
if (t != null) {
w.thread = t;
workers.add(w);
int nt = ++poolSize;
if (nt > largestPoolSize)
largestPoolSize = nt;
}
return t;
}
privatefinalclass Worker implements Runnable {
/**
* The runLock is acquired and released surrounding each task
* execution. It mainly protects against interrupts that are
* intended to cancel the worker thread from instead
* interrupting the task being run.
*/
privatefinal ReentrantLock runLock = new ReentrantLock();
/**
* Initial task to run before entering run loop. Possibly null.
*/
private Runnable firstTask;
/**
* Per thread completed task counter; accumulated
* into completedTaskCount upon termination.
*/
volatilelongcompletedTasks;
/**
* Thread this worker is running in. Acts as a final field,
* but cannot be set until thread is created.
*/
Thread thread;
Worker(Runnable firstTask) {
this.firstTask = firstTask;
}
/**
* Runs a single task between before/after methods.
*/
privatevoidrunTask(Runnable task) {
final ReentrantLock runLock = this.runLock;
runLock.lock();
try {
/*
* Ensure that unless pool is stopping, this thread
* does not have its interrupt set. This requires a
* double-check of state in case the interrupt was
* cleared concurrently with a shutdownNow -- if so,
* the interrupt is re-enabled.
*/
//当线程池的执行状态为关闭等,则执行当前线程的interrupt()操作
if (runState < STOP &&
Thread.interrupted() &&
runState >= STOP)
thread.interrupt();
/*
* Track execution state to ensure that afterExecute
* is called only if task completed or threw
* exception. Otherwise, the caught runtime exception
* will have been thrown by afterExecute itself, in
* which case we don't want to call it again.
*/
boolean ran = false;
beforeExecute(thread, task);
try {
task.run();
ran = true;
afterExecute(task, null);
++completedTasks;
} catch (RuntimeException ex) {
if (!ran)
afterExecute(task, ex);
throw ex;
}
} finally {
runLock.unlock();
}
}
/**
* Main run loop
*/
publicvoid run() {
try {
Runnable task = firstTask;
firstTask = null;
//判断是否存在需要执行的任务
while (task != null || (task = getTask()) != null) {
runTask(task);
task = null;
}
} finally {
//如果没有,则将工作线程移除,当poolSize为0是则尝试关闭线程池
workerDone(this);
}
}
}
/* Utilities for worker thread control */
/**
* Gets the next task for a worker thread to run. The general
* approach is similar to execute() in that worker threads trying
* to get a task to run do so on the basis of prevailing state
* accessed outside of locks. This may cause them to choose the
* "wrong" action, such as trying to exit because no tasks
* appear to be available, or entering a take when the pool is in
* the process of being shut down. These potential problems are
* countered by (1) rechecking pool state (in workerCanExit)
* before giving up, and (2) interrupting other workers upon
* shutdown, so they can recheck state. All other user-based state
* changes (to allowCoreThreadTimeOut etc) are OK even when
* performed asynchronously wrt getTask.
*
* @return the task
*/
Runnable getTask() {
for (;;) {
try {
int state = runState;
if (state > SHUTDOWN)
returnnull;
Runnable r;
if (state == SHUTDOWN) // Help drain queue
r = workQueue.poll();
//当线程池大于corePoolSize,同时,存在执行超时时间,则等待相应时间,拿出队列中的线程
elseif (poolSize > corePoolSize || allowCoreThreadTimeOut)
r = workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS);
else
//阻塞等待队列中可以取到新线程
r = workQueue.take();
if (r != null)
return r;
//判断线程池运行状态,如果大于corePoolSize,或者线程队列为空,也或者线程池为终止的工作线程可以销毁
if (workerCanExit()) {
if (runState >= SHUTDOWN) // Wake up others
interruptIdleWorkers();
returnnull;
}
// Else retry
} catch (InterruptedException ie) {
// On interruption, re-check runState
}
}
}
/**
* Performs bookkeeping for an exiting worker thread.
* @param w the worker
*/
//记录执行任务数量,将工作线程移除,当poolSize为0是则尝试关闭线程池
void workerDone(Worker w) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
completedTaskCount += w.completedTasks;
workers.remove(w);
if (--poolSize == 0)
tryTerminate();
} finally {
mainLock.unlock();
}
}