FutureTask 源码分析
1.前言
FutureTask
表示异步任务(即当一个线程需要等待另一个线程把某个任务执行完后它才能继续执行,)实现了RunnableFuture
接口,而RunnableFuture
又继承了Runnable
接口和Future
接口。
2.Future接口
Future接口被设计用来代表一个异步操作的执行结果。你可以用它来获取一个操作的执行结果、取消一个操作、判断一个操作是否已经完成或者是否被取消。
method | description |
---|---|
get() |
获取执行结果,如果任务还在执行中,就阻塞等待 |
get(long timeout, TimeUnit unit) |
指定等待的时间, 如果指定时间内任务没有完成, 则会抛出TimeoutException 异常 |
cancel(boolean mayInterruptIfRunning) |
尝试取消一个任务的执行,它的返回值是boolean类型,表示取消操作是否成功 |
isCancelled() |
判断任务是否被取消了。如果一个任务在正常执行完成之前被cancel掉了, 则返回true |
isDone() |
如果一个任务已经结束,则返回true。注意, 这里的任务结束包含了以下三种情况:正常执行完毕、抛出异常、被取消 |
3.RunnableFuture接口
RunnableFuture
接口同时实现了Runnable
接口和Future
接口。1
2
3
4
5
6
7public interface RunnableFuture<V> extends Runnable, Future<V> {
/**
* Sets this Future to the result of its computation
* unless it has been cancelled.
*/
void run();
}
问:既然已经继承了Runnable,该接口自然就继承了run方法,为什么要在该接口的内部再写一个run方法?
答:单纯从理论上来说,这里确实是没有必要的,再多写一遍,应该是为了看上去直观一点,便于文档或者UML图展示。
4.FutureTask
4.1.核心属性
(1)stateFutureTask
中状态由state
属性来表示,它是由volatile
修饰的,确保了不同线程对它修改的可见性。state
的值代表了任务在运行过程中的状态,总共有7种状态:包括了1个初始态(NEW),2个中间态(COMPLETING、INTERRUPTING)和4个终止态(NORMAL、EXCEPTIONAL、CANCELLED、INTERRUPTED)。1
2
3
4
5
6
7
8private 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;// 任务被中断
(2)waiterwaiters
表示等待队列的头结点。同一时刻可能有多个线程都在获取该任务的执行结果,如果该任务还在执行过程中,那么这些线程就要进入等待队列中挂起,知道任务执行完毕被唤醒。1
private volatile WaitNode waiters;
FutureTask
中的等待队列是一个单向链表。1
2
3
4
5static final class WaitNode {
volatile Thread thread;
volatile WaitNode next;
WaitNode() { thread = Thread.currentThread(); }
}
(3)runnerrunner
属性表示执行FutureTask
中的Task
的线程。
问:为什么需要一个属性来记录执行任务的线程呢?
答:这是为了中断或取消任务做准备的,只有知道执行任务的线程是谁,我们才能去中断它。1
private volatile Thread runner;
(4)callablecallable