學習Android的人對AsyncTask應該都不陌生,這個類是基于消息機制封裝的一個類,目的是友善開發者使用。對AsyncTask的基本使用方法就不贅述了,郭霖和鴻洋的部落格中都寫得很清楚了,感謝二位大神。這裡記錄一些使用AsyncTask時的小細節。
關于AsyncTask隻能被執行一次
準确來講,是一個AsyncTask對象隻能被執行一次,即同一個AsyncTask對象,不能多次調用其execute()方法。
為什麼呢?原因大概是同一個任務,執行的肯定是相同的邏輯,可能涉及到對同一塊記憶體區域的讀寫,如果開啟一個以上的線程進行相同的任務,由于線程執行時間的不确定性,無法保證資料的原始性,會造成混亂(可能内部沒有鎖吧)。
那如何防止開發者多次調用execute()方法呢?也很簡單,在AsyncTask對象初始化的時候在其中設定一個final變量的引用,執行execute()之前先檢查該變量,并且在開始執行後對該變量進行指派。這樣第二次執行execute()方法的時候會檢測到不同的該變量,那麼這時候直接報錯就好了。
參考文獻:http://blog.csdn.net/lintcgirl/article/details/48440543
關于AsyncTask内部線程的排程
在API10以前,AsyncTask同時能運作5個線程,其餘線程必須等待。
在API10之後,使用execute()方法開啟的AsyncTask,使用同一個線程池,且所有的任務串行執行,也就是說同時隻有一個任務在執行,當該任務執行完畢後,後面的任務才能執行。這不是開倒車嗎?之前還能同時執行5個,現在隻能同時執行一個?其實并不是,Google同時提供了executeOnExecutor()方法供開發者使用非預設的線程池。顧名思義,要在該方法中傳入一個Executor對象才行。
關于Executor的說明請看這篇文章:
Java并發程式設計
同時Google還提供了兩個預定義的線程池(還有比這更貼心的嗎?):
1. executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR) —和API10之前一樣,可以同時執行5個任務。
2. executeOnExecutor(AsyncTask.SERIAL_EXECUTOR) —和execute()一樣,隻能同時執行一個。
如果想自定義線程池,可以這樣寫:
Executor exec = new ThreadPoolExecutor(, , ,
TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
關于線程池的初始化可以參考上面的文章或下面的參考文章:
參考文獻:
http://blog.csdn.net/hitlion2008/article/details/7983449
PS:我一直在思考“封裝”這個概念,對于老手來說,封裝确實友善了使用,但是對于新手來說,封裝也隐藏了内部的實作細節,使得新手隻知其然而不知其是以然,不出問題還好,一出問題就束手無策了。是以我覺得,如果時間和精力允許的話,對于封裝過的子產品還是盡量了解下其内部基本實作會比較好。