AsyncTask引發(fā)的問題

最近寫一個(gè)android小應(yīng)用,用到了AsyncTask發(fā)現(xiàn)一些問題,寫篇日志避免日后再犯相同的錯(cuò)誤,也給遇到與我

相同問題和疑惑的小伙伴們點(diǎn)思路。

AsyncTask的基本使用方法這里不再贅述,直接切入主題。

我用的SDK4.0,代碼(片段)如下:

[java]view plaincopy

packagecom.lic.centerctrl;

importjava.util.HashMap;

importjava.util.Map;

importjava.util.concurrent.ExecutorService;

importjava.util.concurrent.Executors;

importcom.lic.activity.ActivityInterFace;

importandroid.app.Activity;

importandroid.app.Service;

importandroid.content.Context;

importandroid.content.Intent;

importandroid.os.AsyncTask;

importandroid.os.IBinder;

publicclassMainServiceextendsService{

privatestaticTask?task;//當(dāng)前執(zhí)行任務(wù)

privatestaticMap?allActivitys?=newHashMap();//緩存activity集合

privatestaticExecutorService?exec?=?Executors.newSingleThreadExecutor();

@Override

publicvoidonStart(Intent?intent,intstartId)?{

super.onStart(intent,?startId);

MainAsyncTask?asyncTask?=newMainAsyncTask();

//asyncTask.execute(task);

//asyncTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR,?task);

//asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,?task);

//asyncTask.executeOnExecutor(Executors.newFixedThreadPool(2),?task);

asyncTask.executeOnExecutor(exec,?task);

}

privatefinalclassMainAsyncTaskextendsAsyncTask{

privateTask?task;

@Override

protectedObject?doInBackground(Object...?params)?{

Object?result?=null;

task?=?(Task)params[0];

switch(task.getTaskID())?{

caseTask.TASK_USER_LOGIN:

try{

Thread.sleep(3000);

System.out.println("任務(wù)"+task.getTaskID()+"?Thread?id:?"+Thread.currentThread().getId());

}catch(InterruptedException?e)?{

e.printStackTrace();

}

break;

case2:

System.out.println("任務(wù)"+task.getTaskID()+"?Thread?id:?"+Thread.currentThread().getId());

break;

}

returnresult;

}

@Override

protectedvoidonPostExecute(Object?result)?{

super.onPostExecute(result);

ActivityInterFace?aif;

switch(task.getTaskID())?{

caseTask.TASK_USER_LOGIN:

aif?=?(ActivityInterFace)allActivitys.get("LoginActivity");

aif.refresh(1,?result);

break;

case2:

aif?=?(ActivityInterFace)allActivitys.get("LoginActivity");

aif.refresh(2,?result);

break;

default:

break;

}

}

}

/**

*?添加新任務(wù)

*?@param?task

*/

publicstaticvoidaddTask(Context?context,?Task?task)?{

MainService.task?=?task;

context.startService(newIntent("mainService"));

}

/**

*?緩存activity

*?@param?activity

*/

publicstaticvoidaddActivity(Activity?activity)?{

String?path?=?activity.getClass().getName();

String?name?=?path.substring(path.lastIndexOf(".")+1);

allActivitys.put(name,?activity);

}

@Override

publicIBinder?onBind(Intent?intent)?{

returnnull;

}

}

當(dāng)我執(zhí)行兩次調(diào)用asyncTask.execute(task);時(shí)發(fā)現(xiàn)只有當(dāng)?shù)谝淮蔚娜蝿?wù)完成后才執(zhí)行下一下任務(wù)!!怎么回事?

AyncTask不是號(hào)稱異步線程池嗎?既然是線程池那么多任務(wù)執(zhí)行時(shí)應(yīng)該可以并發(fā)執(zhí)行啊,至少兩個(gè)任務(wù)可以并發(fā)執(zhí)

行,以前看過一個(gè)視頻,人家的就可以啊!糾結(jié)了一下午,通過查閱資料和自己的動(dòng)手實(shí)驗(yàn)終于把問題搞明白了。

原來在SDK3.0以前的版本執(zhí)行asyncTask.execute(task);時(shí)的確是多線程并發(fā)執(zhí)行的,線程池大小為5,最大可大

128個(gè),google在3.0以后的版本中做了修改,將asyncTask.execute(task);修改為了順序執(zhí)行,即只有當(dāng)一個(gè)的實(shí)例

的任務(wù)完成后在執(zhí)行下一個(gè)實(shí)例的任務(wù)。

那么怎么才能并發(fā)執(zhí)行呢,很簡(jiǎn)單,3.0后新增了一個(gè)方法executeOnExecutor(Executorexec,Object... params),

該方法接受2個(gè)參數(shù),第一個(gè)是Executor,第二個(gè)是任務(wù)參數(shù)。第一個(gè)是線程池實(shí)例,google為我們預(yù)定義了兩種:

第一種是AsyncTask.SERIAL_EXECUTOR,第二種是AsyncTask.THREAD_POOL_EXECUTOR,顧名思義,第一

種其實(shí)就像3.0以后的execute方法,是順序執(zhí)行的。第二種就是3.0以前的execute方法,是可以并發(fā)執(zhí)行的。我們直

接用asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, task);就可以多任務(wù)并發(fā)執(zhí)行了。

既然executeOnExecutor第一個(gè)參數(shù)是Executor,那么我們可以自定義Executor嗎?當(dāng)然可以,Executor主要由四

種類型newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor

(具體使用解析可以看我上一篇文章點(diǎn)擊打開鏈接),可是當(dāng)我這樣使用

asyncTask.executeOnExecutor(Executors.newFixedThreadPool(1), task);或者

asyncTask.executeOnExecutor(Executors.newSingleThreadExecutor, task);并沒有像我想象的與

asyncTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, task);那樣是單線程順序執(zhí)行,而是像

asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, task);是多線程并發(fā)執(zhí)行的,我不是

已經(jīng)規(guī)定newFixedThreadPool的線程池?cái)?shù)量是1或者是newSingleThreadExecutor單線程了么!怎么回事呢?原來程

序在每次調(diào)用asyncTask.executeOnExecutor(Executors.newFixedThreadPool(2), task)時(shí)會(huì)獲取一個(gè)新的Executor對(duì)

象,這個(gè)對(duì)象內(nèi)的線程只執(zhí)行對(duì)應(yīng)的task,所以無論哪種情況每個(gè)task都有一個(gè)新的線程來執(zhí)行,即并發(fā)執(zhí)行。

知道原因就好辦了,我們定義個(gè)一全局靜態(tài)變量

private static ExecutorService exec = Executors.newSingleThreadExecutor();程序在每次調(diào)用

asyncTask.executeOnExecutor(exec, task);時(shí)是使用的同一個(gè)Executor,執(zhí)行效果如下:

當(dāng)Executor類型為:private static ExecutorService exec = Executors.newFixedThreadPool(2);只有兩個(gè)線程在執(zhí)行

任務(wù)

當(dāng)Executor類型為:private static ExecutorService exec = Executors.newSingleThreadExecutor();只有一個(gè)線程在執(zhí)行任務(wù)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前段時(shí)間遇到這樣一個(gè)問題,有人問微信朋友圈的上傳圖片的功能怎么做才能讓用戶的等待時(shí)間較短,比如說一下上傳9張圖片,...
    加油碼農(nóng)閱讀 1,285評(píng)論 0 2
  • 簡(jiǎn)介 1. 線程分類 主線程(UI線程) : 處理和界面相關(guān)的事情. 子線程 : 處理耗時(shí)操作. Android中...
    王世軍Steven閱讀 976評(píng)論 0 2
  • 原文鏈接:http://blog.csdn.net/u010687392/article/details/4985...
    xpengb閱讀 1,461評(píng)論 0 1
  • 當(dāng)某個(gè)應(yīng)用組件啟動(dòng)且該應(yīng)用沒有運(yùn)行其他任何組件時(shí),Android 系統(tǒng)會(huì)使用單個(gè)執(zhí)行線程為應(yīng)用啟動(dòng)新的 Linux...
    小蕓論閱讀 1,812評(píng)論 0 12
  • AsyncTask是一只命途多舛的小麻雀,為什么說它命途多舛,因?yàn)樗恢北环磸?fù)折騰,從Android 1.6之前,...
    geniusmart閱讀 3,625評(píng)論 3 37

友情鏈接更多精彩內(nèi)容