AsyncTask兩種線程池
http://bbs.51cto.com/thread-1114378-1.html (API 3.0以后):
1.THREAD_POOL_EXECUTOR, 異步線程池
使用
首先創建一個繼承自AsyncTask的MyAsyncTask類,然后調用
原理
1.
2.
3.核心線程無超時機制,非核心線程在閑置時間的超時時間為
4.任務隊列的容量為
corePoolSize
=CPU核心數+1;
2.
maximumPoolSize
=2倍的CPU核心數+1;
3.核心線程無超時機制,非核心線程在閑置時間的超時時間為
1s
;
4.任務隊列的容量為
128
。
當一個任務通過asynct.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, 0)方法欲添加到線程池時:
- 如果此時線程池中的數量小於corePoolSize,即使線程池中的線程都處於空閑狀態,也要創建新的線程來處理被添加的任務。
- 如果此時線程池中的數量等於 corePoolSize,但是緩沖隊列 workQueue未滿,那么任務被放入緩沖隊列。
- 如果此時線程池中的數量大於corePoolSize,緩沖隊列workQueue滿,並且線程池中的數量小於maximumPoolSize,建新的線程來處理被添加的任務。
- 如果此時線程池中的數量大於corePoolSize,緩沖隊列workQueue滿,並且線程池中的數量等於maximumPoolSize,那么通過 handler所指定的策略來處理此任務。
- 當線程池中的線程數量大於 corePoolSize時,如果某線程(非核心線程)空閑時間超過keepAliveTime,線程將被終止。這樣,線程池可以動態的調整池中的線程數。
核心線程corePoolSize、任務隊列workQueue、最大線程maximumPoolSize,如果三者都滿了,使用handler處理被拒絕的任務(一般為
拋出java.util.concurrent.RejectedExecutionException異常
)。

2.SERIAL_EXECUTOR,同步線程池
使用
它是默認的Executor,所以可以直接調用,所以可以有兩種調用方法。
原理
SERIAL_EXECUTOR在THREAD_POOL_EXECUTOR的基礎上添加了一個mTasks的集合來保證任務順序執行(異步)
AsyncTask在不同SDK版本中的區別
舊版本
通過查閱官方文檔發現,AsyncTask首次引入時,異步任務是在一個獨立的線程中順序地執行,也就是說一次只能執行一個任務,不能並行地執行,從1.6開始,AsyncTask中引入了線程池,支持同時執行5個異步任務,也就是說同時只能有5個線程運行,超過的線程只能等待,等待前面的線程某個執行完了才被調度和運行。換句話說,如果一個進程中的AsyncTask實例個數超過5個,那么假如前5個都運行很長時間的話,那么第6個只能等待機會了。這是AsyncTask的一個限制,而且對於2.3以前的版本無法解決。如果你的應用需要大量的后台線程去執行任務,那么你只能放棄使用AsyncTask,自己創建線程池來管理Thread,或者干脆不用線程池直接使用Thread也無妨。不得不說,雖然AsyncTask較Thread使用起來比較方便,但是它最多只能同時運行5個線程,這也大大局限了它的實力,你必須要小心的設計你的應用,錯開使用AsyncTask的時間,盡力做到分時,或者保證數量不會大於5個,否則就可能遇到上面提到的問題。
從1.6開始,AsyncTask中引入的線程池:
1、線程池中的工作線程少於5個時,將會創建新的工作線程執行異步任務(紅色表示新任務,下同)
2、線程池中已經有5個線程,緩沖隊列未滿,異步任務將會放到緩沖隊列中等待
3、線程池中已經有5個線程,緩沖隊列已滿,那么線程池將新開工作線程執行異步任務
問題:Android的設備一般不超過2個cpu核心,過多的線程會造成線程間切換頻繁,消耗系統資源。
4、線程池中已經有128個線程,緩沖隊列已滿,如果此時向線程提交任務,將會拋出RejectedExecutionException
問題:拋出的錯誤不catch的話會導致程序FC。
新版本
可能是Google意識到了AsyncTask的局限性了,從Android 3.0開始對AsyncTask的API做出了一些調整:每次只啟動一個線程執行一個任務,完成之后再執行第二個任務,也就是相當於只有一個后台線程在執行所提交的任務
(
如上 “
Android AsyncTask兩種線程池分析和總結
”所述
)