要研究Android的AsyncTask之前,要先搞明白FutureTask和Executor類:
FutureTask是什么:
FutureTask實際上是一個任務的操作類,它並不啟動新線程,只是在自己所在線程上操作,任務的具體實現是構造FutureTask時提供的,實現自Callable<V>接口,FutureTask不知道具體的任務是什么,它只知道如何調度任務,如:
- 如何啟動任務:在FutureTask的run()方法中(實現自Runnable.run()),調用Callable.call()方法來啟動任務,Callable.call()方法中是任務的具體實現;
- 如何取消任務:在cancel()里,中斷執行任務的線程,記錄任務結束狀態,並調用done()方法來執行用戶實現的操作;
- 如何返回任務的運行結果:如果任務還在執行,則阻塞線程(使用LockSupport.park()),直到任務結束才返回結果,用戶可以通過get()方法來獲取結果,同樣當任務運行結束時,會調用down()來執行用戶實現的操作。
使用FutureTask的好處是,更輕松的對任務進行管理,而不是像Runnable那樣扔進線程后就啥也不能做了。
Executor是什么:
Executor顧名思義是任務執行者,它不關心是什么任務,只關心如何執行任務。Executor是個Interface,具體如何執行任務要看怎么實現這個接口,你可以這樣實現:
class DirectExecutor implements Executor {
@Override public void execute(Runnable r) { r.run(); } }
也可以這樣實現:
class ThreadPerTaskExecutor implements Executor {
@Override public void execute(Runnable r) { new Thread(r).start(); } }
這兩種實現的區別顯而易見,java文檔還提供了另一個Executor實現的例子:
class SerialExecutor implements Executor { final Queue tasks = new ArrayDeque(); final Executor executor; Runnable active; SerialExecutor(Executor executor) { this.executor = executor; }
@Override public synchronized void execute(final Runnable r) { tasks.offer(new Runnable() { public void run() { try { r.run(); } finally { scheduleNext(); } } }); if (active == null) { scheduleNext(); } } protected synchronized void scheduleNext() { if ((active = tasks.poll()) != null) { executor.execute(active); } } }
這個實現的意思是,嚴格按照用戶提交的順序來執行任務。Android的AsyncTask就使用了這個例子。
AsyncTask是如何實現的:
AsyncTask實現的關鍵地方在構造函數和executeOnExecutor()函數里。
- 首先看下構造函數:
public AsyncTask() { mWorker = new WorkerRunnable<Params, Result>() { public Result call() throws Exception { mTaskInvoked.set(true); Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//任務的具體實現 return postResult(doInBackground(mParams)); } }; mFuture = new FutureTask<Result>(mWorker) { @Override protected void done() { try { postResultIfNotInvoked(get()); } catch (InterruptedException e) { android.util.Log.w(LOG_TAG, e); } catch (ExecutionException e) { throw new RuntimeException( "An error occured while executing doInBackground()", e.getCause()); } catch (CancellationException e) { postResultIfNotInvoked(null); } } }; }
代碼中WorkerRunnable實現自Callable,所以mWorker就是任務的具體實現(call()中的doInBackground())。通過對FutureTask的說明可以知道,mFuture是mWorker的操作類,它不僅用來實現對AsyncTask任務的操作(cancel,get等),最主要的,實現了mWorker執行結束的操作:
private void postResultIfNotInvoked(Result result) { final boolean wasTaskInvoked = mTaskInvoked.get(); if (!wasTaskInvoked) { postResult(result); } } private Result postResult(Result result) { @SuppressWarnings("unchecked") Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(this, result)); message.sendToTarget(); return result; } private static final InternalHandler sHandler = new InternalHandler(); private static class InternalHandler extends Handler { @SuppressWarnings({ "unchecked", "RawUseOfParameterizedType" }) @Override public void handleMessage(Message msg) { AsyncTaskResult result = (AsyncTaskResult) msg.obj; switch (msg.what) { case MESSAGE_POST_RESULT: // There is only one result result.mTask.finish(result.mData[0]); break; case MESSAGE_POST_PROGRESS: result.mTask.onProgressUpdate(result.mData); break; } } } private void finish(Result result) { if (isCancelled()) { onCancelled(result); } else { onPostExecute(result); } mStatus = Status.FINISHED; }
FutureTask和Handler共同實現了任務結束的操作,代碼很簡單,不贅述。
- 接下來是executeOnExecutor()函數的實現:
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) { 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; exec.execute(mFuture); return this; }
AsyncTask是通過execute或executeOnExecutor啟動的,通過上邊對Executor的介紹可以知道,在executeOnExecutor()中的exec.execute(mFuture)這一行就是根據exec的實現方式來啟動mFuture了,問題的關鍵是exec是如何實現execute()的。在execute中可以看到AsyncTask提供了一個默認的sDefaultExecutor,這個sDefaultExecutor是什么呢:
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); } } }
默認情況下,sDefaultExecutor就是SerialExecutor類,通過源碼可以看到,SerialExecutor是一個嚴格按照用戶提交順序來執行任務的執行者,其中scheduleNext()函數用來啟動下一個任務:
protected synchronized void scheduleNext() { if ((mActive = mTasks.poll()) != null) { THREAD_POOL_EXECUTOR.execute(mActive); } }
THREAD_POOL_EXECUTOR就是真正啟動任務的Executor:
public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor( CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
ThreadPoolExecutor是java自己實現的一種Executor,顧名思義,是個提供線程池的Executor。
由上可以知道,當調用AsyncTask的execute()函數時,AsyncTask會按用戶提交任務的順序,在線程池里串行的執行任務(當前任務運行結束,再運行下一個)。
當然用戶也可以提供自己的Executor來改變AsyncTask的運行方式。