线程池顾名思义,是放线程的池子,线程池在项目中使用的还是比较多的,那为什么要用线程池呢?主要有以下优势:
Executor作为线程池的顶级接口,只有一个execute方法
public interface Executor {
/**
* 执行一个任务,但并不要求是同步执行还是异步执行,这取决于实现者。
* command表示一个需要执行的任务
*/
void execute(Runnable command);
}
ExecutorService扩展了Executor接口,添加了获取任务返回值的sumbit方法,关闭线程池的shutDown和shutDownNow等方法
public interface ExecutorService extends Executor {
/**
* 关闭线程池,但会把提交给线程池的任务都执行完再关闭
*/
void shutdown();
/**
* 立即关闭线程池,给正在执行的任务发中断指令,并返回队列中未执行的任务
*/
List<Runnable> shutdownNow();
/**
* 线程池是否被关闭
*/
boolean isShutdown();
boolean isTerminated();
boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException;
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);
<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;
}
AbstractExecutorService作为一个抽象类实现了ExecutorService接口,并实现了该接口的部分方法,最主要的是实现了submit方法,这里也只介绍sumbit方法。
public abstract class AbstractExecutorService implements ExecutorService {
/**
* 入参是Runnable,返回值为Future
* 这个方法的关键逻辑主要是newTaskFor方法和execute方法。
*/
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null);
execute(ftask);
return ftask;
}
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;
}
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}
/**
* 这个方法仅仅是将Runnable转换成一个RunnableFuture,具体实现在FutureTask构造方法中
*/
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);
}
}
FutureTask类结构体系
FutureTask类实现了RunnableFuture接口,而RunnableFuture接口又扩展了Future和Runnable接口。
Future接口代表了异步任务的结果。有获取任务结果的方法get(),还有取消任务的方法cancel(),
public interface Future<V> {
/**
* 取消任务
*/
boolean cancel(boolean mayInterruptIfRunning);
/**
* 任务是否被取消
*/
boolean isCancelled();
/**
* 任务是否完成
*/
boolean isDone();
/**
* 获取任务计算结果,阻塞直到任务完成
*/
V get() throws InterruptedException, ExecutionException;
/**
* 获取计算任务,阻塞指定的时间,如果还没有获取到则抛出TimeoutException
*/
V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
}
Runnable作为Thread的顶级接口只有一个run方法。没有返回值不抛出异常。
public interface Runnable {
void run();
}
也看下Callable接口,也是只有一个call方法,但有返回值,也可以抛出异常。
public interface Callable<V> {
V call() throws Exception;
}
RunnableFuture接口整合了Runnable和Future接口,表示一个Future也是一个Runnable.
public interface RunnableFuture<V> extends Runnable, Future<V> {
/**
* 执行该方法成功则会设置一个Future在结果中
*/
void run();
}
之前看到ExecutorService接口的submit方法有Runnable参数,也有Callable参数的方法,从newTaskFor方法可以看到都封装在了FutureTask中。接下来我们看看FutureTask类。
FutureTask作为RunnableFuture一个实现类
/**
* 任务的执行状态,volatile修饰,保证可见性
* 初始化的时候为NEW状态,状态可能的变化过程:
* NEW -> COMPLETING -> NORMAL -- 正常执行
* NEW -> COMPLETING -> EXCEPTIONAL -- 抛出异常
* 以上两种情况在run()方法中设置的,以下两种情况实在cancel方法中设置的
* NEW -> CANCELLED -- 取消
* NEW -> INTERRUPTING -> INTERRUPTED -- 中断
*/
private volatile int state;
private static final int NEW = 0;
private static final int COMPLETING = 1;
private static final int NORMAL = 2;
private static final int EXCEPTIONAL = 3;
private static final int CANCELLED = 4;
private static final int INTERRUPTING = 5;
private static final int INTERRUPTED = 6;
/** 封装的callable,Runnable也封装在里面 */
private Callable<V> callable;
/** get方法的返回结果,也可能是一个Exception */
private Object outcome; // non-volatile, protected by state reads/writes
/** 执行这个callable的线程 */
private volatile Thread runner;
/** 等待者 */
private volatile WaitNode waiters;
// WaitNode仅仅是封装了当前线程的单向链表
static final class WaitNode {
volatile Thread thread;
volatile WaitNode next;
WaitNode() {
thread = Thread.currentThread(); }
}
两个构造函数,一个接收Callable,一个接收Runnable.
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW; // ensure visibility of callable
}
public FutureTask(Runnable runnable, V result) {
// 将Runnable转换为Callable,这里使用的是适配器模式
this.callable = Executors.callable(runnable, result);
this.state = NEW; // ensure visibility of callable
}
public static <T> Callable<T> callable(Runnable task, T result) {
if (task == null)
throw new NullPointerException();
return new RunnableAdapter<T>(task, result);
}
// 适配器模式:实现目标接口,依赖原接口,目标接口方法调用原有接口方法,从而达到适配的目的
static final class RunnableAdapter<T> implements Callable<T> {
final Runnable task;
final T result;
RunnableAdapter(Runnable task, T result) {
this.task = task;
this.result = result;
}
public T call() {
task.run();
return result;
}
}
该方法可以在任务执行完成之后获取任务的返回值,如果任务没有执行完则一直阻塞。
public V get() throws InterruptedException, ExecutionException {
int s = state;
if (s <= COMPLETING)// 表示是初始状态或处理中状态,需要阻塞直到执行成功
s = awaitDone(false, 0L);
return report(s);
}
/**
* 等待完成 或 因中断或超时而中止
* timed:是否使用时间等待
* nanos:使用时间等待的时间,单位纳秒
*/
private int awaitDone(boolean timed, long nanos) throws InterruptedException {
final long deadline = timed ? System.nanoTime() + nanos : 0L;// 等待截至时间,0表示无线等待
WaitNode q = null;
boolean queued = false;
for (;;) {
if (Thread.interrupted()) {
removeWaiter(q);
throw new InterruptedException();
}
int s = state;
if (s > COMPLETING) {
// 表示不在初始状态和处理中,直接返回
if (q != null)
q.thread = null;
return s;
}
else if (s == COMPLETING) // 如果正在执行任务,则让出cpu时间片
Thread.yield();
else if (q == null) // 表示在初始状态
q = new WaitNode();
else if (!queued) // 第二次循环仍然在初始状态
queued = UNSAFE.compareAndSwapObject(this, waitersOffset, q.next = waiters, q);// 将当前线程放在链表头部
else if (timed) {
// 第三次循环仍然在初始状态,如果设置了等待时间则线程阻塞等待的时间
nanos = deadline - System.nanoTime();
if (nanos <= 0L) {
removeWaiter(q); // 删除该节点
return state;
}
LockSupport.parkNanos(this, nanos);
}
else // 第三次循环仍然在初始状态,且没有设置等待时间,则进行阻塞直到被唤醒
LockSupport.park(this);
}
}
// 这个方法很简单,正常状态返回结果,其他状态都抛异常
private V report(int s) throws ExecutionException {
Object x = outcome;
if (s == NORMAL)
return (V)x;
if (s >= CANCELLED)
throw new CancellationException();
throw new ExecutionException((Throwable)x);
}
从之前的submit方法源码中可以看出,execute(futureTask)将futureTask作为Runnable执行了,所以会执行这个run()方法。
run方法对真正要执行的任务进行了控制,如果不是NEW状态就不会执行任务,执行的结果或者异常放outcome属性中,然后改变state。
public void run() {
// 先将runner设置为当前线程,不是新建状态直接返回
if (state != NEW || !UNSAFE.compareAndSwapObject(this, runnerOffset, null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
// 处于新建状态才执行
V result;
boolean ran;
try {
result = c.call(); // 这里会去调用真正的方法
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex); // 设置异常
}
if (ran)
set(result); // 设置返回结果
}
} finally {
runner = null;
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s); // 等待state变成已中断
}
}
// NEW -> COMPLETING(瞬间) -> EXCEPTIONAL(最终)
protected void setException(Throwable t) {
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
outcome = t;
UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state
finishCompletion(); // 唤醒所有等待的线程
}
}
// NEW -> COMPLETING(瞬间) -> NORMAL(最终)
protected void set(V v) {
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
outcome = v;
UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
finishCompletion();
}
}
取消任务。如果任务状态不为NEW,即任务已经执行完成,则直接返回false。
if mayInterruptIfRunning == true. NEW -> INTERRUPTING -> 修改线程中断标志 -> INTERRUPTED(终态)
else NEW -> CANCELLED(终态)
public boolean cancel(boolean mayInterruptIfRunning) {
if (!(state == NEW && // 如果不是NEW状态,直接返回false
UNSAFE.compareAndSwapInt(this, stateOffset, NEW,
mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
return false;
try {
// in case call to interrupt throws exception
if (mayInterruptIfRunning) {
try {
Thread t = runner;
if (t != null)
t.interrupt();
} finally {
// final state
UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
}
}
} finally {
finishCompletion();
}
return true;
}
执行这个任务但不设置结果,状态还是初始状态(NEW),可以重复执行多次。方法逻辑跟run()方法完全一样,只是少了设置结果这一步。
protected boolean runAndReset() {
if (state != NEW || // 如果不是新建状态直接返回false
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return false;
boolean ran = false;
int s = state;
try {
Callable<V> c = callable;
if (c != null && s == NEW) {
try {
c.call(); // don't set result
ran = true;
} catch (Throwable ex) {
setException(ex);
}
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
return ran && s == NEW;
}
FutureTask封装了执行者Runner和需要执行的任务Callable。然后通过状态state控制任务的执行,但这种控制我认为只能算是伪控制,无法控制正在进行的任务-,只能控制设置结果和改变中断标志位。
值得注意的是,在任务执行的过程中状态还是NEW,任务执行完成之后才会将NEW状态改变,所以在调用cancel方法的时候,如果任务没有执行,那么直接修改状态使任务不会再执行,但如果任务已经在执行中了,也仅仅是控制不设置任务返回结果。