參考
http://www.reibang.com/p/79cc3c5fc9a3
http://blog.csdn.net/majihua817/article/details/51658465
以下用法和源碼分析基于android-27(即版本android 8.1.0)
要點總結(jié):
1.進(jìn)程所有AsyncTask默認(rèn)并不是并行執(zhí)行的飞盆,通常默認(rèn)的 使用execute執(zhí)行 的AsyncTask是排隊按順序執(zhí)行的,同一時間內(nèi)只有一個AsyncTask會運行;
2.進(jìn)程中使用executeOnExecutor(Executor exec,Params...params)根據(jù)傳入的線程池效果,可以實現(xiàn)同一時間多個AsyncTask異步執(zhí)行的效果;
3.常用的回調(diào)方法有:onPreExecute()、doInBackground(Params... params)种远、onProgressUpdate(Progress... values)、onPostExecute(Result result)
a. 執(zhí)行順序為onPreExecute -> doInBackground--> (onProgressUpdate)->onPostExecute
b. onPreExecute: 運行在ui線程顽耳,當(dāng)代碼執(zhí)行AsyncTask.execute(Params...params)后會被調(diào)用坠敷,一般可用于界面上一些初始化操作,比如彈出下載對話框等;
c. doInBackground:運行在后臺非ui線程射富,用來處理耗時的任務(wù)膝迎,如下載、數(shù)據(jù)處理等胰耗;
d. onProgressUpdate:運行在ui線程限次,可用來處理界面上的一些進(jìn)度更新相關(guān)操作;在doInBackground中調(diào)用publishProgress后柴灯,可觸發(fā)onProgressUpdate卖漫;
e. 當(dāng)然onPreExecute也可以使用publishProgress觸發(fā)onProgressUpdate,只是二者都是ui線程费尽,所以并沒有實際意義;
f. 注意的是publishProgress也是使用的handler發(fā)送消息來觸發(fā)的onProgressUpdate,所以注意的是
doInBackground沒人為干預(yù)的話并不會因此堵塞等待onProgressUpdate執(zhí)行完畢g. onPostExecute:運行在ui線程,可用于界面提示操作完成懊亡,在doInBackground執(zhí)行完使用return后調(diào)用依啰;
h.源碼中對這些重要回調(diào)方法都有對應(yīng)的@MainThread乎串、@WorkerThread線程注解店枣,但這個注解目前主要用于IDE編譯檢查錯誤用的,實際上execute等依舊可以在子線程中調(diào)用叹誉,當(dāng)然onPreExecute此時就不能處理ui界面鸯两,否則會拋出異常;但建議調(diào)用的地方和注解一致
4.執(zhí)行過一個次或者正在執(zhí)行的AsyncTask不能再次通過execute或者executeOnExecutor進(jìn)行重復(fù)執(zhí)行
5.使用executeOnExecutor并行執(zhí)行的話,根據(jù)傳入的線程池的設(shè)置會有隊列大小的限制长豁,通常直接使用AsyncTask中AsyncTask.THREAD_POOL_EXECUTOR這個線程池的話:
//cpu核數(shù),假設(shè)4
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
//核心線程數(shù),3
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
//最大同時執(zhí)行的線程數(shù)9
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
//空閑線程超過30秒被回收
private static final int KEEP_ALIVE_SECONDS = 30;
//等待隊列允許的最大數(shù)量為128
private static final BlockingQueue<Runnable> sPoolWorkQueue =new LinkedBlockingQueue<Runnable>(128);
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
sPoolWorkQueue, sThreadFactory);
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
(假設(shè)終端cpu數(shù)目為4)因為該線程池運行同時運行的最大線程數(shù)為9,等待隊列最大為128钧唐,如果每一個asynctask的doInBackground中耗時非常久,一次性添加超過9+128=137個task的話(比如listview中一次性創(chuàng)建),那么將會引起異常java.util.concurrent.RejectedExecutionException
6.使用execute的話匠襟,因為有隊列緩存(沒大小限制钝侠,除非內(nèi)存爆掉),串行執(zhí)行酸舍,所以不存在線程池中任務(wù)超出大小的情況
7.AsyncTaskd的cancel方法只是簡單把標(biāo)志位改為true帅韧,最后使用Thread.interrupt去中斷線程執(zhí)行,但是這并不保證會馬上停止執(zhí)行啃勉,所以可以在doInBackground中使用isCancelled來判斷任務(wù)是否被取消
要點解釋
(來自參考資料http://www.reibang.com/p/79cc3c5fc9a3)
在Android 1.5剛引入的時候忽舟,AsyncTask的execute是串行執(zhí)行的;到了Android 1.6直到Android 2.3.2淮阐,又被修改為并行執(zhí)行了叮阅,這個執(zhí)行任務(wù)的線程池就是THREAD_POOL_EXECUTOR,因此在一個進(jìn)程內(nèi)泣特,所有的AsyncTask都是并行執(zhí)行的浩姥;但是在Android 3.0以后,如果你使用execute函數(shù)直接執(zhí)行AsyncTask状您,那么這些任務(wù)是串行執(zhí)行的及刻。因此結(jié)論就來了:Android 3.0以上,AsyncTask默認(rèn)并不是并行執(zhí)行的竞阐。
由于同一個進(jìn)程的AsyncTask都是在一個線程池中缴饭,如果默認(rèn)是并行的,那么多個線程同時執(zhí)行多個task中的doInBackground操作骆莹,而doInBackground又訪問修改相同的資源颗搂,這邊往往會忽略對資源的同步處理問題特幔,經(jīng)常會導(dǎo)致不可預(yù)料的錯誤結(jié)果隐轩,為此默認(rèn)情況下使用execute執(zhí)行的AsyncTask默認(rèn)為串行執(zhí)行;
如果處理好資源同步問題,可以使用executeOnExecutor傳入合適的線程池及志,來達(dá)到AsyncTask并行執(zhí)行的效果;
優(yōu)缺點總結(jié)
優(yōu)點:
- 1.封裝后實現(xiàn)簡單的的子線程和ui線程間的一個切換,省去了用戶需要子線程更新ui界面繁瑣的操作
缺點(參考http://blog.csdn.net/goodlixueyong/article/details/45895997):
1.需要注意串行還是并行執(zhí)行运褪,在1.5是串行宾袜,1.6-2.3.2是并行,3.0之后默認(rèn)使用execute時串行貌嫡,如果使用executeOnExecutor則是并行比驻;
2.所謂的串行,實際上主要是針對doInBackground方法里面的操作而言的岛抄,串行時并不會等到task中onPostExecute執(zhí)行完才觸發(fā)下一份asynctask,只要doInBackground執(zhí)行完成就會促發(fā)下一個asynctask
3.可能導(dǎo)致內(nèi)存泄露或者ui更新異常問題别惦,如果是activity中非靜態(tài)內(nèi)部asynctask子類,默認(rèn)隱式持有一個activity的引用夫椭,在activity銷毀之前掸掸,注意要停止asynctask;不然后臺線程一直運行蹭秋,導(dǎo)致了內(nèi)存泄露扰付,還可能在要更新ui時,該view已經(jīng)不存在而導(dǎo)致異常仁讨;
4.如果activity因為轉(zhuǎn)屏重建或者被后臺異常終結(jié)羽莺,之前運行的asynctask還會持有一個之前activity的引用,更新這個無效的引用上的view需要注意對view有效性的判斷
5.并行執(zhí)行的時候陪竿,需要考慮下線程池能夠處理的任務(wù)大小
使用方法
聲明MyAsyncTask繼承并實現(xiàn)AsyncTask相關(guān)回調(diào):
public class MyAsyncTask extends AsyncTask<String, Integer, Boolean>{
String TAG="MyAsyncTask";
public MyAsyncTask(String tag) {
super();
this.TAG=tag;
}
//doInBackground開始之前調(diào)用,ui線程,可用于界面上的一些初始化操作禽翼,比如彈出下載對話框
@Override
protected void onPreExecute() {
Log.d(TAG,"onPreExecute "+Thread.currentThread());
Toast.makeText(context,"onPreExecute",Toast.LENGTH_SHORT).show();
}
//用于執(zhí)行后臺任務(wù),非ui線程族跛,用于處理耗時任務(wù)闰挡,下載,數(shù)據(jù)處理等
@Override
protected Boolean doInBackground(String... params) {
Log.d(TAG,"doInBackground "+Thread.currentThread());
int count = params.length;
for(int i=0;i<count;i++){
//判斷任務(wù)是否取消礁哄,取消則停止,用戶調(diào)用AsyncTask.cancel()后設(shè)置該標(biāo)志位
//調(diào)用AsyncTask.cancel()并不能直接停止一個asynctask,
// 需要在doInBackground/onProgressUpdate/onPreExecute手動判斷該標(biāo)志位
if(isCancelled()){
return false
}
String p = params[i];
Log.d(TAG,"doInBackground:"+p);
publishProgress(i);
}
return true;
}
//當(dāng)后臺任務(wù)doInBackground調(diào)用了publishProgress(Progress...)方法后长酗,這個方法會被調(diào)用
//用于執(zhí)行處理過程中的進(jìn)度更新之類,ui線程,可用于更新下載對話框的進(jìn)度條
@Override
protected void onProgressUpdate(Integer... values) {
Log.d(TAG,"onProgressUpdate:"+values[0]+" "+Thread.currentThread());
Toast.makeText(context,"onProgressUpdate:"+values[0],Toast.LENGTH_SHORT).show();
}
//當(dāng)后臺任務(wù)doInBackground執(zhí)行完畢并通過return語句進(jìn)行返回時桐绒,這個方法就會被調(diào)用
//ui線程夺脾,可用于界面更新處理完成
@Override
protected void onPostExecute(Boolean aBoolean) {
Log.d(TAG,"onPostExecute:"+aBoolean+" "+Thread.currentThread());
Toast.makeText(context,"onPostExecute",Toast.LENGTH_SHORT).show();
}
//AsyncTaskd的cancel方法只是簡單把標(biāo)志位改為true,最后使用Thread.interrupt去中斷線程執(zhí)行茉继,但是這并不保證會馬上停止執(zhí)行咧叭,所以可以在doInBackground中使用isCancelled來判斷任務(wù)是否被取消
//ui線程,可用于取消后關(guān)閉ui界面提示等
@Override
protected void onCancelled(Boolean aBoolean) {
Log.d(TAG,"onCancelled:"+aBoolean+" "+Thread.currentThread());
}
}
創(chuàng)建相關(guān)實例并執(zhí)行AsyncTask:
測試一:普通使用
Log.d(TAG,"btn1 start");
MyAsyncTask myAsyncTask =new MyAsyncTask("task1"); //創(chuàng)建AsyncTask子類實例
myAsyncTask.execute("參數(shù)1","參數(shù)2"); //開始執(zhí)行
Log.d(TAG,"btn1 end");
**日志輸出**:
btn1 start
onPreExecute Thread[main,5,main] //可以看見調(diào)用execute后烁竭,onPreExecute立馬執(zhí)行
btn1 end
doInBackground Thread[AsyncTask #1,5,main]
doInBackground:參數(shù)1
doInBackground:參數(shù)2
//doInBackground調(diào)用publishProgress后,由handler觸發(fā)onProgressUpdate菲茬,與doInBackground為2個線程異步執(zhí)行
onProgressUpdate:0 Thread[main,5,main]
onProgressUpdate:1 Thread[main,5,main]
onPostExecute:true Thread[main,5,main] //全部操作完成后調(diào)用
測試二:多個asyncTask使用驗證串行執(zhí)行
Log.d(TAG,"btn1 start");
MyAsyncTask myAsyncTask =new MyAsyncTask("task1");
MyAsyncTask myAsyncTask2 =new MyAsyncTask("task2");
myAsyncTask.execute("參數(shù)1","參數(shù)2");
myAsyncTask2.execute("參數(shù)1","參數(shù)2");
Log.d(TAG,"btn1 end");
日志輸出:
btn1 start
//可以看見各自調(diào)用execute后,task1,task2的onPreExecute立馬執(zhí)行,互不影響
task1: onPreExecute Thread[main,5,main]
task2: onPreExecute Thread[main,5,main]
btn1 end
task1: doInBackground Thread[AsyncTask #1,5,main] //doInBackground是按序執(zhí)行的
task1: doInBackground:參數(shù)1
task1: doInBackground:參數(shù)2
task2: doInBackground Thread[AsyncTask #2,5,main]
task2: doInBackground:參數(shù)1
task2: doInBackground:參數(shù)2
//onProgressUpdate和onProgressUpdate也是按序執(zhí)行的
//這邊看到可能存在后續(xù)asyncTask執(zhí)行doInBackground過程中婉弹,
前面的task才剛觸發(fā)onProgressUpdate和onPostExecute
task1: onProgressUpdate:0 Thread[main,5,main]
task1: onProgressUpdate:1 Thread[main,5,main]
task1: onPostExecute:true Thread[main,5,main]
task2: onProgressUpdate:0 Thread[main,5,main]
task2: onProgressUpdate:1 Thread[main,5,main]
task2: onPostExecute:true Thread[main,5,main]
測試三:并行執(zhí)行:
MyAsyncTask myAsyncTask =new MyAsyncTask("task1");
MyAsyncTask myAsyncTask2 =new MyAsyncTask("task2");
myAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"參數(shù)1","參數(shù)2");
myAsyncTask2.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"參數(shù)1","參數(shù)2");
日志輸出(doInBackground 添加Thread.sleep方便模擬):
btn1 start
task1: onPreExecute Thread[main,5,main]
task2: onPreExecute Thread[main,5,main]
//task1與task2的doInBackground部分交替執(zhí)行
task1: doInBackground Thread[AsyncTask #1,5,main]
task1: doInBackground:參數(shù)1
task2: doInBackground Thread[AsyncTask #2,5,main]
task2: doInBackground:參數(shù)1
btn1 end
task1: onProgressUpdate:0 Thread[main,5,main]
task2: onProgressUpdate:0 Thread[main,5,main]
task1: doInBackground:參數(shù)2
task2: doInBackground:參數(shù)2
task1: onProgressUpdate:1 Thread[main,5,main]
task2: onProgressUpdate:1 Thread[main,5,main]
task1: onPostExecute:true Thread[main,5,main]
task2: onPostExecute:true Thread[main,5,main]
從測試中可以看出onPreExecute在各自AsyncTask調(diào)用execute后立即執(zhí)行睬魂,后續(xù)源碼分析可知道onPreExecute不由handler觸發(fā),否則可能與doInBackground執(zhí)行時序有差別;
測試二中:
后續(xù)從源碼分析可以知道使用execute觸發(fā)的AsyncTask中的doInBackground部分實際上是在線程池中排隊執(zhí)行的镀赌,所以只有一個任務(wù)的doInBackground執(zhí)行完氯哮,才會獲取下一個任務(wù)的doInBackground進(jìn)行執(zhí)行;
從源碼分析可以知道onProgressUpdate商佛、onPostExecute是通過handler消息控制的喉钢,本身也是按序執(zhí)行的;多個AsyncTask的不同的生命周期步驟其實會有穿插威彰;
從日志輸出和源碼原理可知,AsyncTask的按序執(zhí)行相對來講有一定的不足出牧,不會等待一個AsyncTask完整執(zhí)行完后onPreExecute -> doInBackground--> (onProgressUpdate)->onPostExecute,后下一個AsyncTask才允許開始它的生命周期;
測試三中:
驗證了執(zhí)行線程池并行執(zhí)行的效果
源碼分析
AsyncTask開始執(zhí)行工作的入口函數(shù)為AsyncTask.execute,所以從該方法入手查看
AsyncTask源碼
execute函數(shù)
@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
注解上也表明該方法運行需要在ui線程運行,為什么需要呢穴肘?此為問題一歇盼;
這邊使用execute觸發(fā)會使用默認(rèn)的線程池SerialExecutor sDefaultExecutor,
該線程池實際上只起到一個隊列控制评抚,保存task依次按順序執(zhí)行豹缀;
假設(shè)需要并發(fā)執(zhí)行AsyncTask,則可以直接使用executeOnExecutor方法
傳入合適的線程池就可以達(dá)到效果慨代;
接著查看調(diào)用的executeOnExecutor所執(zhí)行的操作
executeOnExecutor函數(shù)
@MainThread
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;
}
首先該方法會進(jìn)行一個AsyncTask狀態(tài)的判斷,如果該AsyncTask已經(jīng)運行過或者正在運行則拋出異常邢笙,
每個AsyncTask只允許直接或者間接調(diào)用一次executeOnExecutor;狀態(tài)判斷AsyncTask尚處于等待狀態(tài)Status.PENDING,則將該狀態(tài)標(biāo)識為Status.RUNNING正在運行狀態(tài)等待后續(xù)線程池排隊執(zhí)行侍匙;
-
注意氮惯,接著立即執(zhí)行onPreExecute()方法,也就是用于初始化ui控件準(zhǔn)備工作的方法;
這邊說明了前面2個問題:- 1想暗、onPreExecute()方法在execute()方法調(diào)用后會立即執(zhí)行;
- 2妇汗、execute()假設(shè)在非ui線程調(diào)用,則onPreExecute()也在非ui線程執(zhí)行说莫,將導(dǎo)致拋出更新ui異常,此為上述問題一,需要要求execute或或者executeOnExecutor在ui線程執(zhí)行;
- 3杨箭、雖然注解和源碼注釋要求要在ui線程執(zhí)行execute()或者executeOnExecutor,但假設(shè)你沒有重寫onPreExecute()進(jìn)行ui操作(默認(rèn)是空操作),是可以在子線程中執(zhí)行的(可能IDE會有提示錯誤储狭,但運行的時候沒出現(xiàn)異常)互婿,當(dāng)然強(qiáng)烈建議執(zhí)行線程和注解一致
mWorker.mParams = params;
exec.execute(mFuture);
然后將傳入的params參數(shù)賦值給mWorker.mParams(params后續(xù)會傳遞給doInBackground進(jìn)行處理),調(diào)用線程池exec處理mFuture;
這邊需要對mWorker、mFuture和線程池exec進(jìn)行分析,首先對于exec可以看出傳入的是線程池SerialExecutor
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
對于線程池SerialExecutor
- 通過上述分析知道SERIAL_EXECUTOR的定義是靜態(tài)的辽狈,也就是類共享的慈参,同一進(jìn)程共用一個線程池,
- 下面分析會知道SERIAL_EXECUTOR主要用來維護(hù)asynctask任務(wù)隊列,按先進(jìn)先出的原則順序取出任務(wù)交給實際執(zhí)行的線程池THREAD_POOL_EXECUTOR進(jìn)行執(zhí)行
- 對于THREAD_POOL_EXECUTOR也是靜態(tài)的,并且執(zhí)行完一個后才會處理下一個任務(wù)刮萌;
- 因此如果同時創(chuàng)建多個AsyncTask后使用execute進(jìn)行執(zhí)行驮配,默認(rèn)是加入到SERIAL_EXECUTOR進(jìn)行排隊等待執(zhí)行的,一個時刻只有一個AsyncTask在執(zhí)行;
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
// We want at least 2 threads and at most 4 threads in the core pool,
// preferring to have 1 less than the CPU count to avoid saturating
// the CPU with background work
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE_SECONDS = 30;
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
public Thread newThread(Runnable r) {
return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
}
};
//實際執(zhí)行任務(wù)的線程池,注意是靜態(tài)的僧凤,所以AsyncTask共用
public static final Executor THREAD_POOL_EXECUTOR;
static {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
sPoolWorkQueue, sThreadFactory);
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}
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(); //即調(diào)用 FutureTask mFuture.run()方法
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
//THREAD_POOL_EXECUTOR為實際執(zhí)行任務(wù)的線程池
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
可以看出該SerialExecutor在被調(diào)用execute后畜侦,會將一個任務(wù)添加到隊列ArrayDeque中(即前面exec.execute(mFuture)),execute傳入的是實現(xiàn)了Runnable接口的類FutureTask的實例mFuture,SerialExecutor的主要作用實際上時維護(hù)任務(wù)的隊列躯保,按順序取出任務(wù)交給實際執(zhí)行任務(wù)的線程池THREAD_POOL_EXECUTOR
第一個執(zhí)行時mActive == null所以會調(diào)用scheduleNext,(按先進(jìn)先出)從隊列中拿出一個任務(wù)交給線程池THREAD_POOL_EXECUTOR進(jìn)行執(zhí)行:
public void run() {
try {
r.run(); //即調(diào)用 FutureTask mFuture.run()方法
} finally {
scheduleNext(); //執(zhí)行完畢后旋膳,獲取下一個任務(wù)進(jìn)行處理
}
}
執(zhí)行的即為傳入的mFuture.run()方法,執(zhí)行完成后會再次調(diào)用scheduleNext獲取并執(zhí)行下一個AsyncTask任務(wù)途事。
下面看一下FutureTask.run()方法所做的操作
FutureTask類
//FutureTask類構(gòu)造函數(shù),這邊傳入的實際上是實現(xiàn)了Callable接口的WorkerRunnable類對象mWorker
//mWorker與mFuture的關(guān)聯(lián)在AsyncTask創(chuàng)建時構(gòu)造函數(shù)中完成
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW; // ensure visibility of callable
}
//線程池THREAD_POOL_EXECUTOR中執(zhí)行的方法
public void run() {
if (state != NEW ||
!U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call(); //調(diào)用的是mWorker的call方法
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}
由上述可知验懊,線程池THREAD_POOL_EXECUTOR中執(zhí)行的mFuture.run()方法中實際上會調(diào)用result = c.call()即實現(xiàn)了Callable接口的類的WorkerRunnable對象mWorker.call();
其中WorkerRunnable類對象mWorker、FutureTask類對象mFuture的創(chuàng)建和關(guān)聯(lián)位于AsyncTask構(gòu)造函數(shù)中尸变;
AsyncTask構(gòu)造函數(shù)
//部分需要聯(lián)系使用的成員變量
//注意是靜態(tài)的,類共享一個線程池
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
//注意是靜態(tài)的變量,類共享一個handler
private static InternalHandler sHandler;
private final WorkerRunnable<Params, Result> mWorker;
private final FutureTask<Result> mFuture;
private final Handler mHandler;
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*/
public AsyncTask() {
this((Looper) null);
}
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*
* @hide
*/
public AsyncTask(@Nullable Handler handler) {
this(handler != null ? handler.getLooper() : null);
}
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*
* @hide
*/
public AsyncTask(@Nullable Looper callbackLooper) {
mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
? getMainHandler()
: new Handler(callbackLooper);
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Result result = null;
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
result = doInBackground(mParams); //線程池中最終執(zhí)行doInBackground
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);
throw tr;
} finally {
postResult(result);
}
return result;
}
};
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 occurred while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
}
由上可以看出默認(rèn)構(gòu)造函數(shù)會執(zhí)行
public AsyncTask(@Nullable Looper callbackLooper),傳入?yún)?shù)為null,
此時mHandler = getMainHandler()獲取到一個主線程的handler;
創(chuàng)建了mWorker和mFuture對象义图,并通過mFuture = new FutureTask<Result>(mWorker)
完成mFuture與mWorker的一個關(guān)聯(lián);
后續(xù),線程池THREAD_POOL_EXECUTOR中執(zhí)行的mFuture.run()會執(zhí)行到mWorker.call()由上可看出:
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
result = doInBackground(mParams); //線程池中最終執(zhí)行doInBackground
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);
throw tr;
} finally {
postResult(result);
}
觸發(fā)執(zhí)行了doInBackground(mParams)后召烂,通過postResult(result)將結(jié)果result通過hander發(fā)出最終在handler的ui線程中觸發(fā)了onPostExecute回調(diào);
postResult函數(shù)
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
使用handler發(fā)送處理結(jié)束的消息
getMainHandler函數(shù)
private static Handler getMainHandler() {
synchronized (AsyncTask.class) {
if (sHandler == null) {
sHandler = new InternalHandler(Looper.getMainLooper());
}
return sHandler;
}
}
該方法簡單的創(chuàng)建一個handler通過Looper.getMainLooper()使得該handler運行于ui線程,注意的是sHandler是靜態(tài)的碱工,也就是說進(jìn)程所有的AsyncTask共享一個handler進(jìn)行處理消息;
InternalHandler類和finish方法
private static class InternalHandler extends Handler {
public InternalHandler(Looper looper) {
super(looper);
}
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
public void handleMessage(Message msg) {
AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
switch (msg.what) {
//接收消息并且在ui線程回調(diào)執(zhí)行finish最終調(diào)用onPostExecute方法
case MESSAGE_POST_RESULT:
// There is only one result
result.mTask.finish(result.mData[0]);
break;
//接收消息并且在ui線程回調(diào)執(zhí)行onProgressUpdate方法
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
該handler主要用于接收消息MESSAGE_POST_PROGRESS后在ui線程執(zhí)行onProgressUpdate方法,
或者接收MESSAGE_POST_RESULT后,最終在ui線程執(zhí)行onPostExecute/onCancelled方法,AsyncTask中2個重要的方法onProgressUpdate奏夫、onPostExecute由該handler執(zhí)行怕篷;
private void finish(Result result) {
if (isCancelled()) {
//任務(wù)執(zhí)行完之后,如果用戶之前調(diào)用了AsyncTask.cancle()則觸發(fā)onCancelled
onCancelled(result);
} else {
//否則觸發(fā)onPostExecute
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
源碼總結(jié)
- 1.AsyncTask中存在靜態(tài)的2個線程池SerialExecutor酗昼、ThreadPoolExecutor廊谓,以及一個靜態(tài)的ui線程的handler
SerialExecutor implements Executor : sDefaultExecutor
ThreadPoolExecutor : THREAD_POOL_EXECUTOR:
進(jìn)程中對于使用execute開始的所有的AsyncTask順序排隊執(zhí)行
- 2.AsyncTask構(gòu)造函數(shù)中,初始化了handler麻削,WorkerRunnable mWorker蒸痹,F(xiàn)utureTask mFuture,并且將mWorker關(guān)聯(lián)到mFuture:
mWorker = new WorkerRunnable<Params, Result>(){..}..
mFuture = new FutureTask<Result>(mWorker) {..}..
-
3.使用execute的時候:
- 會調(diào)用executeOnExecutor()并傳遞SerialExecutor
- 在executeOnExecutor()中執(zhí)行onPreExecute呛哟,并將mFuture傳遞給SerialExecutor進(jìn)行排隊
- SerialExecutor按先進(jìn)先出的順序依次取出任務(wù)給ThreadPoolExecutor進(jìn)行處理叠荠,處理調(diào)用的是mFuture.run()方法實際上會執(zhí)行到mWorker.call()里面的doInBackground方法,執(zhí)行完成后通過handler觸發(fā)onPostExecute方法;
過程中如果調(diào)用publishProgress會通過handler觸發(fā)onProgressUpdate;
如果要并行執(zhí)行asynctask則不使用execute而是直接使用executeOnExecutor傳遞給合適的線程池竖共,跳過SerialExecutor的排隊步驟;
掃描關(guān)注微信公眾號: