一、线程池继承结构
二、Executor接口
public interface Executor {
/**
* Executes the given command at some time in the future. The command
* may execute in a new thread, in a pooled thread, or in the calling
* thread, at the discretion of the {@code Executor} implementation.
*
* @param command the runnable task
* @throws RejectedExecutionException if this task cannot be
* accepted for execution
* @throws NullPointerException if command is null
*/
void execute(Runnable command);
}
Executor接口位于最顶层,只有一个抽象方法,在ThreadPoolExecutor类中给出了具体实现。该方法用于提交一个任务,但任务何时执行、由哪个线程执行是不确定的,替代了以往new Thread(new (RunnableTask())).start()的方法,将任务的提交、调度、执行解耦。该方法没有返回值,因此无法判断任务是否成功执行。
三、ExecutorService接口
public interface ExecutorService extends Executor {
// 启动一个关闭命令,已提交的任务执行完后就关闭,同时不接收新任务
// 如果已经关闭该方法调用无其他作用
void shutdown();
// 试图停止正在执行的任务,不再接受新的任务,返回等待执行的任务列表
// 终止线程的方法是通过Thread.interrupt()实现的,该方法的成功执行是有条件的,
// 即当线程是因sleep、wait、join阻塞时当线程因sleep、wait、join阻塞时,否则调用interrupt()方法不能中断线程,
// 所以线程池可能不能立即关闭,可能要等任务执行完才能关闭
List<Runnable> shutdownNow();
// 线程池是否已关闭
boolean isShutdown();
// 在调用shutdown()或shutdownNow()后,是否所有任务均执行完毕,是的话返回true
// 该方法要在shutdown()或shutdownNow()调用后且满足条件才能返回true
boolean isTerminated();
// timeout:超时时间,unit:单位
// 常与shutdown()搭配使用,判断调用shutdown()后,线程池等待正在执行的线程执行完毕后关闭是否超时boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException;
// 用于提交一个任务,并且有返回值,可通过future判断任务是否执行成功
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);
// 批量提交任务,所有任务完成后返回future的一个list
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException;
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException;
// 批量提交任务,当提交的任务有一个执行完毕就可返回,返回的是执行完毕的任务的结果
<T> T invokeAny(Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException;
<T> T invokeAny(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
ExecutorService接口继承了Executor接口,提供了更多的功能,一般定义一个线程池时使用该接口。
四、AbstractExecutorService类
AbstractExecutorService抽象类派生自ExecutorService接口,对该接口的部分方法给出了实现。
1. newTaskFor方法
// 将任务包装成FutureTask,并返回一个RunnableFuture对象,可通过该对象获取执行结果
protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
return new FutureTask<T>(runnable, value);
}
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
return new FutureTask<T>(callable);
}
2. submit方法
用于提交一个任务,并且有返回值,可用于判断任务是否执行成功
// 任务执行成功调用Future的get()方法返回null
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException(); // 若任务为null则抛出异常
RunnableFuture<Void> ftask = newTaskFor(task, null); // 将任务包装成FutureTask
execute(ftask); // 由子类提供具体实现
return ftask;
}
// 任务执行成功调用Future的get()方法返回给定结果
public <T> Future<T> submit(Runnable task, T result) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task, result);
execute(ftask);
return ftask;
}
// 任务执行成功调用Future的get()方法返回给定结果
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}
3. doInvokeAny方法
// 调用invokeAny()时的主要机制
// tasks:任务集合,timed:是否设置超时机制,nanos:超时时间
private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks,
boolean timed, long nanos)
throws InterruptedException, ExecutionException, TimeoutException {
if (tasks == null)
throw new NullPointerException();
int ntasks = tasks.size(); // 任务的数量
if (ntasks == 0)
throw new IllegalArgumentException();
ArrayList<Future<T>> futures = new ArrayList<Future<T>>(ntasks);
// 将执行器包装为ExecutorCompletionService,使得每个任务执行完后,将结果保存在completionQueue中
ExecutorCompletionService<T> ecs =
new ExecutorCompletionService<T>(this);
// 为了提高效率,要在提交新任务之前检查之前提交的任务是否执行完成
try {
// 记录执行异常,使得当我们不能成功获取执行结果时抛出最后得到的一个异常
ExecutionException ee = null;
final long deadline = timed ? System.nanoTime() + nanos : 0L;
Iterator<? extends Callable<T>> it = tasks.iterator();
// 首先提交一个任务,任务数减1,active(正在执行的任务数)加1
futures.add(ecs.submit(it.next()));
--ntasks;
int active = 1;
for (;;) {
Future<T> f = ecs.poll(); // 从completionQueue中取出一个Future
if (f == null) { // 若为空即当前没有任务执行完成
if (ntasks > 0) { // 若还有未执行任务则提交一个新任务
--ntasks;
futures.add(ecs.submit(it.next()));
++active;
}
else if (active == 0) // 若未执行和执行任务数均为0则跳出循环
break;
else if (timed) { // 若所有任务已提交,且无任务执行完成,且设置了超时机制
f = ecs.poll(nanos, TimeUnit.NANOSECONDS);
if (f == null) // 若在时间内未有任务完成则抛出异常
throw new TimeoutException();
nanos = deadline - System.nanoTime();
}
else // 所有任务已提交,没有任务执行完成,没有设置超时机制
f = ecs.take(); // 阻塞直至有任务执行完成
}
if (f != null) { // 有任务执行完成
--active; // 执行任务数减1
try {
return f.get(); // 返回执行结果
} catch (ExecutionException eex) {
ee = eex;
} catch (RuntimeException rex) {
ee = new ExecutionException(rex);
}
}
}
if (ee == null)
ee = new ExecutionException();
throw ee;
} finally {
for (int i = 0, size = futures.size(); i < size; i++) // 方法退出之前取消其他任务
futures.get(i).cancel(true);
}
}
4. invokeAny方法
// 提交任务集合,当有一个任务完成后则返回
public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException {
try {
return doInvokeAny(tasks, false, 0);
} catch (TimeoutException cannotHappen) {
assert false;
return null;
}
}
public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
return doInvokeAny(tasks, true, unit.toNanos(timeout));
}
5. invokeAll方法
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException {
if (tasks == null)
throw new NullPointerException();
ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
boolean done = false;
try {
for (Callable<T> t : tasks) {
RunnableFuture<T> f = newTaskFor(t); // 将每个任务包装成RunnableFuture
futures.add(f);
execute(f); // 提交任务
}
for (int i = 0, size = futures.size(); i < size; i++) {
Future<T> f = futures.get(i);
if (!f.isDone()) {
try {
f.get(); // 是一个阻塞的方法,直到获取正确的值或者抛出异常
} catch (CancellationException ignore) {
} catch (ExecutionException ignore) {
}
}
}
done = true;
return futures;
} finally {
if (!done) // 若出现异常,取消其他正在执行的任务
for (int i = 0, size = futures.size(); i < size; i++)
futures.get(i).cancel(true);
}
}
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
throws InterruptedException {
if (tasks == null)
throw new NullPointerException();
long nanos = unit.toNanos(timeout);
ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
boolean done = false;
try {
for (Callable<T> t : tasks) // 将任务包装成FutureTask并放入列表
futures.add(newTaskFor(t));
final long deadline = System.nanoTime() + nanos;
final int size = futures.size();
// Interleave time checks and calls to execute in case
// executor doesn't have any/much parallelism.
for (int i = 0; i < size; i++) {
execute((Runnable)futures.get(i)); // 提交任务
nanos = deadline - System.nanoTime();
if (nanos <= 0L) // 任务尚未提交完就超时
return futures;
}
for (int i = 0; i < size; i++) {
Future<T> f = futures.get(i);
if (!f.isDone()) {
if (nanos <= 0L) // 任务提交完了,但是存在执行超时的任务
return futures;
try {
f.get(nanos, TimeUnit.NANOSECONDS);
} catch (CancellationException ignore) {
} catch (ExecutionException ignore) {
} catch (TimeoutException toe) {
return futures;
}
nanos = deadline - System.nanoTime();
}
}
done = true;
return futures;
} finally {
if (!done)
for (int i = 0, size = futures.size(); i < size; i++)
futures.get(i).cancel(true);
}
}
五、ThreadPoolExecutor类
1. 关键属性:
- corePoolSize:核心线程数,即使没有任务处理,核心线程也会一直存活。若当前线程数小于核心线程数时,即使有空闲线程,也会创建一个新的线程执行任务。
- maximumPoolSize:最大线程数,即线程池允许创建的最大线程数。
- keepAliveTime:空闲线程的保活时间,当线程空闲时间达到该值时,该线程会退出,直至线程数减至核心线程数。
- unit:keepAliveTime的单位。
- workQueue:工作队列,存放待提交的任务。
- threadFactory:创建线程的工厂。
- handler:当线程池已满而又有任务提交时采用的策略,具体Java 线程池的拒绝策略 RejectedExecutorHandler
// 构造方法
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;
}
2. execute方法
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
// 如果当前线程数少于核心线程数,添加一个新的线程,并将任务提交给该线程
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
// 执行到此处,要么所有线程数大于等于核心线程数,要么addWorker失败
// 若线程池处于running状态,则将任务放置到工作队列
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
// 再次检测线程池的状态,避免在上次检测后线程池被关闭
// 若被关闭,则将任务从任务队列中移除并执行拒绝策略
if (! isRunning(recheck) && remove(command))
reject(command);
// 若线程池处于running状态,且线程数为0,则创建一个新的线程
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
// 若队列满了,则在线程数小于maximumPoolSize的情况下创建一个新线程
// 若创建失败,则执行拒绝策略
else if (!addWorker(command, false))
reject(command);
}
参考:
1. 深度解读 java 线程池设计思想及源码实现 https://juejin.im/entry/59b232ee6fb9a0248d25139a#%E6%80%BB%E7%BB%93
2. 【Java8源码分析】线程池-Executor与ExecutorService的全面剖析 https://blog.csdn.net/linxdcn/article/details/72828362