FutureTask阅读笔记
文章目录
- FutureTask阅读笔记
- 一、简介
- 二、继承关系图
- 三、存储结构
- 四、源码分析
- 内部类
- 属性
- 构造
- 主要方法
- 1、run()相关方法
- 2、get()相关方法
- 3、cancel(boolean t)方法
- 使用Demo
一、简介
通过把普通任务封装成FutureTask来获取执行结果,同时还可以感知任务执行的异常,甚至还可以取消任务
采用异常调用思想,Netty、Dubbo中常见
二、继承关系图
- @FunctionalInterface 声明为函数式接口,这个接口只有一个抽象方法
- Future 未来接口
- Runnable 线程接口
- RunnableFuture 未来+线程接口组合
- WaitNode是FutureTask的内类
三、存储结构
把线程转换成Callable线程,然后封装成FutureTask来进行操作,并且重写了run方法
四、源码分析
内部类
- WaitNode内部类
static final class WaitNode {
volatile Thread thread;
volatile WaitNode next;
WaitNode() { thread = Thread.currentThread(); }
}
属性
/*
* Possible state transitions:
* NEW -> COMPLETING -> NORMAL
* NEW -> COMPLETING -> EXCEPTIONAL
* NEW -> CANCELLED
* NEW -> INTERRUPTING -> INTERRUPTED
*/
private volatile int state;
// 任务初始化状态(新建或还没完成),#开始状态#
private static final int NEW = 0;
// 任务完成状态(任务已执行完成或者执行任务出现异常,但是还没有保存outcome字段)
// NEW到COMPLETING的状态很短,这是一个#中间状态#
private static final int COMPLETING = 1;
// 任务执行完成,并且任务执行结果已经保存到outcome字段,#最终状态#
private static final int NORMAL = 2;
// 任务执行异常,并且异常保存到了outcome字段,#最终状态#
private static final int EXCEPTIONAL = 3;
// 任务还没开始执行或者已经开始执行但是还没有执行完成的时候,
// 用户调用了cancel(false)方法取消任务且不中断任务执行线程,这个时候会转成这个状态,#最终状态#
private static final int CANCELLED = 4;
// 任务还没开始执行或者已经开始执行但是还没有执行完成的时候,
// 用户调用了cancel(true)方法取消任务且要中断任务执行线程,但是还没有中断任务执行线程之前
// 状态 NEW 转换为 INTERRUPTING ,#中间状态#
private static final int INTERRUPTING = 5;
// 调用interrupt()中断任务执行线程之后会从INTERRUPT状态切换为INTERRUPTED,这是一个#最终状态#
private static final int INTERRUPTED = 6;
/** 真正的线程,运行完成(异常完成)后设置为null */
private Callable<V> callable;
/** 返回的结果,或抛出的异常 */
private Object outcome; // non-volatile, protected by state reads/writes
/** 任务的执行者,真正的线程运行后设置为null */
private volatile Thread runner;
/** 等待队列 */
private volatile WaitNode waiters;
构造
/** 构造方法一:把Callable包装成FutureTask */
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW; // ensure visibility of callable
}
/** 构造方法二:把Runnable和V返回对象包装成Callable然后再包装成FutureTask */
public FutureTask(Runnable runnable, V result) {
this.callable = Executors.callable(runnable, result);
this.state = NEW; // ensure visibility of callable
}
主要方法
1、run()相关方法
- run()方法:任务执行
- set(V v )方法:任务正常完成,设置结果
- setException(Throwable t)方法:任务异常完成,设置异常结果
- finishCopletion()方法:任务完成后,执行此方法唤醒队列中其他线程
// 此方法还有一个runAndReset的protected修饰的方法,具有返回true和flase
public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
// state不是新建状态,或 原子更新runner属性为当前线程失败就返回,run失败
return;
try {
// 获取实例线程
Callable<V> c = callable;
// 判断实例线程,不能为空,状态必须是NEW
if (c != null && state == NEW) {
V result;
boolean ran;
try {
// 执行实例线程任务,采用call的觉有返回值
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
// 任务执行失败,设置异常结果
ran = false;
setException(ex);
}
if (ran)
// 任务执行成功,设置返回结果
set(result);
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;//帮助GC
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
// 如果当前的任务线程出现中断,就进行处理
handlePossibleCancellationInterrupt(s);
}
}
/** 调用实例线程异常执行方法 */
protected void setException(Throwable t) {
// 将状态从NEW设置为COMPLETING
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
// 设置返回值
outcome = t;
// 有序原子写state状态为EXCEPTIONAL
UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state
// 调用完成方法
finishCompletion();
}
}
/** 调用实例线程完成返回方法 */
protected void set(V v) {
// 将状态从NEW设置为COMPLETING
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
// 设置返回值
outcome = v;
// 有序原子写state状态为NORMAL
UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
// 调用完成方法
finishCompletion();
}
}
/** 状态为#最终状态#时,调动 :有疑问?什么鬼waiters,请去看get*/
private void finishCompletion() {
// assert state > COMPLETING;
for (WaitNode q; (q = waiters) != null;) {
// 置空队列
if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {
for (;;) {
// 调用者线程
Thread t = q.thread;
if (t != null) {
q.thread = null;
// 如果调用者线程不为null,就唤醒它
LockSupport.unpark(t);
}
WaitNode next = q.next;
if (next == null)
break;
q.next = null; // unlink to help gc
q = next;
}
break;
}
}
// 钩子方法,子类重写
done();
// 设置实例线程为null
callable = null; // to reduce footprint
}
2、get()相关方法
- get():获取返回结果,如果结果就会进入等待队列
- awaitDone(boolean timed,long nanos);把当前线程加入到等待队列
- report:获取返回结果
public V get() throws InterruptedException, ExecutionException {
int s = state;
if (s <= COMPLETING)
// 说线程是NEW或运行完成但是还没保存返回结果的时候
// 就到队列中去等待 ,所以是这个时候
s = awaitDone(false, 0L);
return report(s);
}
/** 把当前线程加入到WaitNode等待队列 */
private int awaitDone(boolean timed, long nanos)
// 只考虑get调用,是不带超时的
throws InterruptedException {
final long deadline = timed ? System.nanoTime() + nanos : 0L;
WaitNode q = null;
boolean queued = false;
for (;;) {
// 处理中断
if (Thread.interrupted()) {
removeWaiter(q);
throw new InterruptedException();
}
int s = state;
// 如果状态大于COMPLETING了,就跳出循环并返回
// 这里是自旋的出口
if (s > COMPLETING) {
if (q != null)
q.thread = null;
return s;
}
// 如果状态等于COMPLETING,
// 说明任务快完成了,就差设置状态到NORMAL或EXCEPTIONAL和设置任务结果
// 那么就让出CPU资源
else if (s == COMPLETING) // cannot time out yet
Thread.yield();
// 如果队列为null,就初始化队列
else if (q == null)
// 用用当前线程去初始化
// WaitNode() { thread = Thread.currentThread(); }
q = new WaitNode();
// 如果未进入队列
else if (!queued)
// 尝试CAS入队
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);
}
}
/** get()方法中,确定过任务线程已经大于COMPLETING,然后就去取值 */
private V report(int s) throws ExecutionException {
Object x = outcome;
// 任务正常结束
if (s == NORMAL)
return (V)x;
// 被取消了,抛CancellationException异常
if (s >= CANCELLED)
throw new CancellationException();
// 执行异常,抛ExecutionException((Throwable)x)异常
throw new ExecutionException((Throwable)x);
}
3、cancel(boolean t)方法
- mayInterruptIfRunning:是否中断执行线程
public boolean cancel(boolean mayInterruptIfRunning) {
// 把任务状态从NEW 修改为 INTERRUPTING(中间状态)或CANCELLED(完成状态)
if (!(state == NEW &&
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;
}
使用Demo
- 利用显示成的submit提交可以返回future来完成
public class FutureTaskTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService threadPool = new ThreadPoolExecutor(5,10,1000L,TimeUnit.SECONDS,new ArrayBlockingQueue<>(5));
List<Future<Integer>> list = new ArrayList<>();
IntStream.range(0,10).forEach(i -> {
Future<Integer> future = threadPool.submit(() -> {
Thread.sleep(1000L);
System.out.println(i);
return i;
});
list.add(future);
});
int sum = 0;
for (Future<Integer> future : list) {
sum += future.get();
}
System.out.println(sum);
}
}