Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 關於Android 3.0以後AsyncTask默認單一線程的分析

關於Android 3.0以後AsyncTask默認單一線程的分析

編輯:關於Android編程

在Android裡需要大量後台操作的情況下,經常會使用到AsyncTask這個類,比如說加載網絡圖片,訪問服務器的接口,一般的使用情境就是實例化一個AsyncTask的對象mTask,復寫AsyncTask的抽象方法doinBackgroud等等,最後執行task.execute(params),然後就可以在UI線程上方便的取得後台線程的執行結果;

AsyncTask執行中最終觸發的是把任務交給線池THREAD_POOL_EXECUTOR來執行,提交的任務並行的在線程池中運行,但這些規則在3.0之後發生了變化,3.0之後提交的任務是串行運行的,執行完一個任務才執行下一個!

先看看3.0以前的代碼;

 

private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 128;
private static final int KEEP_ALIVE = 10;

 


public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);

3.0以前線程池裡核心線程有5個,同時存在的線程數最大不能超過128個,線程池裡的線程都是並行運行的;

 

但是在3.0之後,直接調用execute(params)觸發的是sDefaultExecutor的execute(runnable)方法,而不是原來的THREAD_POOL_EXECUTOR

 

private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE = 1;

public static void execute(Runnable runnable) {
        sDefaultExecutor.execute(runnable);
    }

 

看看這個sDefaultExecutor與原來的THREAD_POOL_EXECUTOR線程池有什麼 差別,sDefaultExecutor實際上是指向SerialExecutor的一個實例,從名字上看是一個順序執行的executor;

 

public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;

 private static class SerialExecutor implements Executor {
        final ArrayDeque mTasks = new ArrayDeque();
        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);
            }
        }
    }

分析SerialExecutor,當提交一個任務,執行一次execute(),向mTasks添加一個runnable,此時mActive為null,接著會執行scheduleNext(),將mActive指向剛剛添加的runbale,並提交到THREAD_POOL_EXECUTOR中執行,接著就線程池中就會執行下面這段代碼;

try {
                        r.run();
                    } finally {
                        scheduleNext();
                    }

當asyncTask提交大量的任務時,會重復之前的流程,任務都添加至mTasks中了,提交第一個任務之後,mActive便不再為Null了,之後的任務如果要被執行就必需等到前一個任務run方法跑完,也就是try{ }語句塊中的run(),前一個任務執行完後,才會調用finally
後面的scheduleNext()從mTasks中取出下一個任務來執行;

 

分析完上面的代碼後,現在對於3.0以後AsyncTask默認情況下同時只存在一個線程順序執行的原理就了解清楚了;

 

如果想要提交的任務在能並行執行呢?這在網絡圖片顯示中還是比較有用的;

AsyncTask也為我們提供了另外一種啟動方法
 

public final AsyncTask executeOnExecutor(Executor exec,Params... params)

這裡可以指定自定義的executor,而不再用SerialExecutor,如果樂意的話當然也可以直接使用用原本的THREAD_POOL_EXECUTOR,這樣就可以保證多個任務並行執行了;

 

 



  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved