目標(biāo)
打算從以下幾個(gè)方面進(jìn)行分析:
1. Callable、Future、FutureTask、Runnable的關(guān)系;
2. 適配器模式;
3. FutureTask實(shí)例;
一、Callable、Future、FutureTask、Runnable的關(guān)系
1.1 Callable
public interface Callable<V> {
V call() throws Exception;
}
1.2 Future
public interface Future<V> {
boolean cancel(boolean mayInterruptIfRunning);
boolean isCancelled();
boolean isDone();
V get() throws InterruptedException, ExecutionException;
V get(long timeout, TimeUnit unit);
}
1.3 RunnableFuture
public interface RunnableFuture<V> extends Runnable, Future<V> {
void run();
}
1.4 Runnable
public interface Runnable {
public abstract void run();
}
1.5 FutureTask
// FutureTask擁有Runnable和Future的共性;
public class FutureTask<V> implements RunnableFuture<V>{
public FutureTask(Callable<V> callable);
public FutureTask(Runnable runnable, V result)
boolean isDone();
void run();
V get();
V get(long timeout, TimeUnit unit);
V call();
}
從上面類的結(jié)構(gòu)可以看出, FutureTask擁有Runnable與Future的共性, Future與Runnable的區(qū)別是后者有返回值, 而前者沒有.
二、適配器模式
在分析FutureTask源碼之前, 其實(shí)很有必要搞懂適配器模式的概念以及特點(diǎn);
2.1 適配器概念
概念:
??適配器模式把一個(gè)類的接口變換成客戶端所期待的另一種接口, 從而使原本因接口不匹配而無法在一起工作的兩個(gè)類能夠在一起工作;
使用場(chǎng)景:
??1、系統(tǒng)需要使用現(xiàn)有的類, 而此類的接口不符合系統(tǒng)的需要, 即接口不兼容.
??2、想要建立一個(gè)可以重復(fù)使用的類, 用于與一些彼此之間沒有太大關(guān)聯(lián)的一些類, 包括一些可能在將來引進(jìn)的類一起工作.
??3、需要一個(gè)統(tǒng)一的輸出接口, 而輸入端的類型不可預(yù)知.
2.2 對(duì)象適配器
對(duì)象適配器模式把適配的類的API轉(zhuǎn)換成目標(biāo)類的API, 與類的適配器模式不同的是, 對(duì)象的適配器模式不是使用繼承關(guān)系連接到Adaptee類, 而是使用代理關(guān)系連接到Adaptee類.

結(jié)合上圖給出一個(gè)demo
// Target角色
public interface FiveVolt {
public int getVolt5();
}
// Adaptee角色, 需要被轉(zhuǎn)換的對(duì)象
public class Volt220 {
public int getVolt220() {
return 220;
}
}
// 對(duì)象適配器模式
public class VoltAdapter implements FiveVolt {
Volt220 mVolt220;
public VoltAdapter(Volt220 adaptee) {
mVolt220 = adaptee;
}
public int getVolt220() {
return mVolt220.getVolt220();
}
@Override
public int getVolt5() {
return 5;
}
}
Adaptee類(Volt220)并沒有提供getVolt5()方法, 而客戶端則期待這個(gè)方法, 為使客戶端能夠使用Adaptee類, 需要提供一個(gè)包裝類Adapter, 這個(gè)包裝類包裝了一個(gè)Adaptee的實(shí)例, 從而此包裝類能夠把Adaptee的API與Target類的API銜接起來, Adapter與Adaptee是委派關(guān)系.
一、單純就FutureTask源碼進(jìn)行分析
1.1 FutureTask兩個(gè)構(gòu)造函數(shù)
private Callable<V> callable;
// 這里直接對(duì)FutureTask內(nèi)部的callable變量進(jìn)行賦值;
public FutureTask(Callable<V> callable) {
this.callable = callable;
this.state = NEW;
}
// 1. 注意這里, 其實(shí)我們也可以借鑒, 假如FutureTask支持Callable, 后來有需求需要支持Runnable,
// 可以考慮將Runnable轉(zhuǎn)換為Callable類型, 當(dāng)我們通過FutureTask觸發(fā)Callable方法時(shí), 實(shí)際是
// 調(diào)用了Callable內(nèi)部的Runnable.run方法;
// 2. 結(jié)合1馬上再描述一下適配器模式的概念:
// 將一個(gè)類的接口變換成客戶端所期待的另一種接口, 從而使原本因接口不匹配而無法在一起工作的兩個(gè)類能夠在一起工作;
public FutureTask(Runnable runnable, V result) {
// 結(jié)合下面兩段代碼可知, 生成一個(gè)中間適配層RunnableAdapter, 然后通過call()最終調(diào)用Runnable.run()方法;
this.callable = Executors.callable(runnable, result);
this.state = NEW;
}
public class Executors {
public static <T> Callable<T> callable(Runnable task, T result) {
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();
// 這里返回傳進(jìn)來的result方法? 這個(gè)值肯定在某處被賦值了;
return result;
}
}
1.2 FutureTask.run
FutureTask通常都是配合線程池一起使用, 而我們知道, 線程池里面會(huì)觸發(fā)Runnable.run的執(zhí)行;
public void run() {
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;
// 1.這里觸發(fā)了Callable.call()方法, 并且獲取其返回值, 結(jié)合上文可知, 假如是以
// 第二種方式初始化的FutureTask, c實(shí)際指向中間適配層RunnableAdapter,
// c.call()內(nèi)部最終調(diào)用了Runnable.run()方法;
// 2.而返回值就是我們?cè)跇?gòu)造FutureTask時(shí)傳進(jìn)去的Result, 這里就很懵逼了, 初始化
// FutureTask時(shí)傳進(jìn)去Result, 任務(wù)還沒開始, Result從何而來呢?
result = c.call();
ran = true;
if (ran)
// 當(dāng)前Runnable.run()執(zhí)行完成以后, 通過set(result)對(duì)outcome進(jìn)行賦值, 從而
// 影響到get()方法;
set(result);
}
} finally {
runner = null;
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}
1.3 FutureTask.get
public V get() throws InterruptedException, ExecutionException {
int s = state;
if (s <= COMPLETING)
// 這里就利用到了生產(chǎn)者-消費(fèi)者模式, 如果當(dāng)前任務(wù)沒有完成, 則調(diào)用get()方法的
// 線程會(huì)一直阻塞在這里, 直到外部線程通過set(result)喚醒當(dāng)前線程;
s = awaitDone(false, 0L);
return report(s);
}
分析完FutureTask源碼之后, 還是有幾個(gè)點(diǎn)不是很明白, 比如get()返回的result其實(shí)是在初始化FutureTask時(shí)傳入的result, 這個(gè)result何時(shí)被賦值?
結(jié)合AsyncTask源碼進(jìn)行再次實(shí)戰(zhàn)分析
二、從AsyncTask源碼對(duì)FutureTask進(jìn)行實(shí)戰(zhàn)
2.1 AsyncTask兩種調(diào)用方式:
??1、創(chuàng)建AsyncTask對(duì)象, 自己實(shí)現(xiàn)doInBackground()方法, 然后調(diào)用execute()方法;
??2、直接調(diào)用AsyncTask內(nèi)部的靜態(tài)execute()方法;
因?yàn)榈谝环N方式用到了FutureTask, 所以先針對(duì)這種方式進(jìn)行分析:
2.2 AsyncTask構(gòu)造函數(shù)
public AsyncTask() {
mWorker = new WorkerRunnable<...>() {
public Result call() throws Exception {...}
};
mFuture = new FutureTask<...>(mWorker) {
@Override
protected void done() {...}
};
}
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
Params[] mParams;
}
2.3 AsyncTask.execute(AsyncTask處理線程的第一種方式)
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params) {
if (mStatus != Status.PENDING) {
switch (mStatus) {
// mState初始值Status.PENDING, 對(duì)于同一個(gè)AsyncTask對(duì)象, 第一次執(zhí)行完execute
// 方法以后, mState = Status.RUNNING/Status.FINISHED, 再次調(diào)用execute方法以后,
// 拋出異常, 這點(diǎn)可以知道AsyncTask的局限性, 不支持連續(xù)多次調(diào)用execute方法;
case RUNNING:
throw new IllegalStateException("Cannot execute task:"
+ " the task is already running.");
case FINISHED:
throw new IllegalStateException("Cannot execute task:"
+ " the task has already been executed "
+ "(a task can be executed only once)");
}
}
mStatus = Status.RUNNING;
onPreExecute();
mWorker.mParams = params;
// 在這之前的操作都是在主線程中進(jìn)行的, 下面代碼進(jìn)入到子線程中, 觸發(fā)mFuture.run()的執(zhí)行;
exec.execute(mFuture);
return this;
}
2.4 AsyncTask.execute(AsyncTask處理任務(wù)的第二種方式)
public static void execute(Runnable runnable) {
sDefaultExecutor.execute(runnable);
}
2.5 AsyncTask.sDefaultExecutor
public class AsyncTask {
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;
public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
}
??execute只接受Runnable對(duì)象, mActive實(shí)際指向FutureTask, 當(dāng)Executor.execute(Runnable)時(shí)會(huì)觸發(fā)Runnable內(nèi)部run方法的執(zhí)行, 而FutureTask此時(shí)接收的是Callable對(duì)象;
FutureTask_Callable :
public class FutureTask {
public FutureTask(Callable<V> callable) {
this.callable = callable;
}
public void run() {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
setException(ex);
}
if (ran)
set(result);
}
}
}
??1、FutureTask內(nèi)部的run()方法又是調(diào)用了Callable對(duì)象的call方法;
??2、Future提供了一系列的控制線程周期的方法;通過AsyncTask的cancel控制FutureTask的生命周期;
所以四者的關(guān)系是:
??1、由于Executor的execute()方法只接收Runnable, 并且會(huì)觸發(fā)Runnable內(nèi)部的run方法的執(zhí)行, 所以FutureTask必須實(shí)現(xiàn)Runnable;
??2、但是Runnable的run方法沒有返回值, 而有些特殊情況又需要拿到最終線程執(zhí)行的結(jié)果, 而Callable剛好可以拿到結(jié)果, 所以在其內(nèi)部持有Callable的引用;
??3、需要控制線程什么什么周期的問題, 而Future剛好提供了這些功能, 所以FutureTask又實(shí)現(xiàn)Future接口;
但是如果FutureTask需要支持Runnable怎么辦?目前run方法內(nèi)部實(shí)際調(diào)用的是Callable的call()方法:
??所以適配器模式在這里發(fā)揮了作用, 也反映了適配器的一個(gè)特點(diǎn), 是為了解決問題而生;
public class FutureTask {
public FutureTask(Runnable runnable, V result) {
this.callable = Executors.callable(runnable, result);
}
}
public class Executors{
public static <T> Callable<T> callable(Runnable task, T result) {
return new RunnableAdapter<T>(task, result);
}
private static final class RunnableAdapter<T> implements Callable<T> {
private final Runnable task;
private final T result;
RunnableAdapter(Runnable task, T result) {
this.task = task;
this.result = result;
}
public T call() {
task.run();
return result;
}
}
}
??FutureTask構(gòu)造函數(shù)支持傳入Runnable對(duì)象, 可以看到此時(shí)傳入的Runnable實(shí)際通過適配器模式被轉(zhuǎn)化為了Callable對(duì)象, 而Callable實(shí)際指向RunnableAdapter, RunnableAdapter內(nèi)部持有Runnable, 內(nèi)部的call方法又會(huì)出發(fā)Runnable的run方法的執(zhí)行;