吐槽:以前看了好多文章和书籍讲FutureTask,讲的很细,但不得要领,还是会忘。绝知此事要躬行,还是得自己亲自分析下源码。
1、FutureTask本质上是Runnable和Callable的实现类,就是一个任务类,主函数也是run()。
2、FutureTask实现了异步任务,怎么实现的?是因为Callable?
不是。Callable.call()与Runnable.run()只是一个很普通的方法,是同步方法。异步方法是因为FutureTask的实现机制,使用了Guard Suspension模式。
下面说下Guard Suspension模式的核心思想,以及Future是如何实现的:
GS模式作用:把同步方法,变为异步方法。
GS模式思想:线程A执行与一般同步方法无异,主要是线程B(异步任务,如FutureTask所在的线程)的执行不一样:异步任务的get()方法调用wait()方法进入wait状态(java有多种实现),等待同步方法call()执行结束(在线程B中运行),通知get方法取消wait状态。这就是GS的主要思想。
示意图如下:
从上图可见,run()和get()是主要角色,run的代码如下:
set()其实很简单,就是返回outcome结果,并调用finishCompletion(),通知get()方法,取消wait状态。
再看下get(),awaitDone()就是进入了wait()状态。其实现是一个for(;;)循环。对应上面的finishCompletion(),我们只需要关注思想,先不管具体实现。
反正awatiDone()的无限循环会被finishCompletion()打破。然后调用report()
public
Vget()
throws
InterruptedException, ExecutionException {
int
s
=
state
;
if
(
s
<=
COMPLETING
)
s
= awaitDone(
false
, 0L);
return
report(
s
);
}
report()实现如下。就是把set()里面设置的outcome传给x,然后返回。
@SuppressWarnings
(
"unchecked"
)
private
Vreport(
int
s
)
throws
ExecutionException {
Object
x
=
outcome
;
if
(
s
==
NORMAL
)
return
(V)
x
;
if
(
s
>=
CANCELLED
)
throw
new
CancellationException();
throw
new
ExecutionException((Throwable)
x
);
}
小结:
1. FutureTask的核心思想是:通过awaitDone()和finishCompletion()实现异步操作。
2. 第1点,被封装为get()/set()。其中get()被外部线程A调用,set()被线程B--FutureTask的run()调用。
3.Callable的call()本质上是同步方法。
4.FutureTask的主函数只运行callable方法,Runnable.run()是通过一个adapter转为Callable的()。
public FutureTask(Runnable runnable, V result) {
this.callable = Executors.callable(runnable, result);
this.state = NEW; // ensure visibility of callable
}
this.callable = Executors.callable(runnable, result);
this.state = NEW; // ensure visibility of callable
}
Executors.callable定义如下:
public static <T> Callable<T> callable(Runnable task, T result) {
if (task == null)
throw new NullPointerException();
return new RunnableAdapter<T>(task, result);
}
if (task == null)
throw new NullPointerException();
return new RunnableAdapter<T>(task, result);
}