構造AsyncTask, 這裏只需理解Worker, Future的概念。注意這裏mWorker 和 mFuture 的關係, 以及 postResult 和done方法。java
AsyncTask使用了模板方法的設計模式, doInBackground是其中的核心,被包裝在mWorker對象中,mWorker對象又被包裝在mFuture對象, mFuture本質是一個runnable
android
/** * Creates a new asynchronous task. This constructor must be invoked on the UI thread. */ public AsyncTask() { mWorker = new WorkerRunnable<Params, Result>() { public Result call() throws Exception { mTaskInvoked.set(true); Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); //noinspection unchecked 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); } } }; }
===============以上是背景。==================設計模式
從execute方法開始,內部調用了executeOnExecutor 方法, 多線程
public final AsyncTask<Params, Progress, Result> execute(Params... params) { return executeOnExecutor(sDefaultExecutor, params); }
這裏的sDefaultExecutor 默認是SERIAL_EXECUTOR,是 SerialExecutor類型對象。 模板方法doInBackground的參數params就是在這裏經過mWorker對象賦值的async
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params) { ... mStatus = Status.RUNNING; onPreExecute(); mWorker.mParams = params; exec.execute(mFuture); return this; }
AsyncTask中有兩個重要的靜態變量:SERIAL_EXECUTOR 和 THREAD_POOL_EXECUTORide
/** * An {@link Executor} that can be used to execute tasks in parallel. */ public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory); /** * An {@link Executor} that executes tasks one at a time in serial * order. This serialization is global to a particular process. */ public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
接下來看 SerialExecutor 的execute 方法, 先把當前task放在隊列mTasks尾部,而後取隊列第一個task經過TREAD_POOL_EXECUTOR執行。 注意execute 和 scheduleNext 都是synchronized 方法, 在AysncTask中SerialExecutor的實例變量SERIAL_EXECUTOR又是一個靜態成員,因此即便咱們在不一樣的線程中new出來不少AyncTask對象分別提交不一樣的任務, 這些任務讓仍然會被串行的加入任務隊列。工具
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(); } } }); //若是當前沒有正在執行的任務就在隊首調度一個新任務, //不然等待當前任務完成,完成後會自動調度下一個任務, 這裏的mActive是包裝後的任務對象 if (mActive == null) { scheduleNext(); } } protected synchronized void scheduleNext() { if ((mActive = mTasks.poll()) != null) { // SERIAL_EXECUTOR調用了THREAD_POOL_EXECUTOR來具體執行任務 //注意這裏的mActive是包裝後的任務對象 THREAD_POOL_EXECUTOR.execute(mActive); } } }
千萬注意,這裏咱們提交的任務是 r , 可是在放入mTasks隊列時對 r 進行了以下的包裝, 這裏包裝後的任務對象是匿名的,假設包裝後的任務叫pr ( pseudo r 的意思) , 那麼pr 的執行包括了兩部分,首先執行具體的任務(r的run方法),而後無論任務執行是否成功(也就是無論r的run方法過程是否發生了異常),接着調度mTasks隊列的下一個任務。因此當使用默認的AsyncTask時,若是有多處提交任務,那麼這些任務將會按串行的方式執行,這就是爲何官方推薦只用AsyncTask執行短時任務, 任務耗時太長的話將會發生相互阻塞,這多是你不想要的!post
mTasks.offer(new Runnable() { public void run() { try { r.run(); } finally { scheduleNext(); } } });
問題到這裏已經清楚了。this
=================end======================spa
接着說一下, TREAD_POOL_EXECUTOR 和 SERIAL_EXECUTOR均可以當作executor使用, 而且TREAD_POOL_EXECUTOR是能夠並行的執行任務的(多線程),可是TREAD_POOL_EXECUTOR對AsyncTask是不可見的,SERIAL_EXECUTOR纔是AsyncTask直接使用的executor對象。 TREAD_POOL_EXECUTOR只是做爲SERIAL_EXECUTOR執行任務的工具,對SERIAL_EXECUTOR來講,它的做用就是能夠提供線程來執行任務。因此若是你想改變AsyncTask不適合執行長時間任務的這個缺陷,須要定製本身的Executor來替換SERIAL_EXECUTOR。