Android獨(dú)有的多線程

一提多線程惑畴,腦子里立馬浮現(xiàn)出各種關(guān)于線程池辐棒、線程同步行剂、線程狀態(tài)的詞匯秕噪,恨不能把線程控制的像控件一樣手拿把攥,儼然已將Android系統(tǒng)提供的線程機(jī)制拋諸腦后厚宰,今天小編就來八一八這些Android獨(dú)有的多線程腌巾。

一、AsyncTask

Sync是同步,Async就是異步了壤躲。先看下異步任務(wù)的使用方法城菊,再分析其源碼實(shí)現(xiàn)备燃。
1.使用方法
AsyncTask<Params, Progress, Result>
第一個(gè)為入?yún)⒌锟耍诙€(gè)為進(jìn)度類型,第三個(gè)為結(jié)果類型并齐。
四個(gè)回調(diào)方法漏麦,
onPreExecute(),主線程中執(zhí)行準(zhǔn)備工作况褪。
doInBackground(Params... params)撕贞,線程池執(zhí)行異步任務(wù),可以調(diào)用publishProgress更新任務(wù)進(jìn)度测垛,它會(huì)調(diào)用onProgressUpdate方法捏膨。返回Result給onPostExecute()。
onProgressUpdate(Progress... values)食侮,主線程執(zhí)行号涯,更新進(jìn)度。
onPostExecute(Result result)锯七,主線程執(zhí)行链快,執(zhí)行結(jié)果的返回值。
onCancelled()眉尸,取消執(zhí)行域蜗。

2.源碼解析

  1. execute()-->executeOnExecutor()-->在3.0之后,第一個(gè)為串行噪猾,第二個(gè)為并行
  2. onPreExecute()-->serialExecutor.execute(mFuture)用于任務(wù)的排隊(duì)-->有一個(gè)ArrayDeque<Runnable>任務(wù)列表霉祸,新來的Runnable會(huì)被插入到隊(duì)列尾部-->
  3. 然后調(diào)用scheduleNext() –>如果沒有正在活動(dòng)的任務(wù),就會(huì)取出一個(gè)任務(wù)執(zhí)行THREAD_POOL_EXECUTOR.execute(mActive)袱蜡,用于執(zhí)行任務(wù)-->
  4. 執(zhí)行WorkerRunnable的call()-->postResult(doInBackground(params))-->
  5. message.sendToTarget()-->在Handler中handleMessage丝蹭,如果是PROGRESS,則回調(diào)onProgressUpdate戒劫;如果是RESULT半夷,則finish()-->onCancelled/onPostExecute(result)。

二迅细、HandlerThread

普通Thread用于執(zhí)行耗時(shí)任務(wù)巫橄。
HandlerThread是使用Handler的Thread,在run()中通過Looper.prepare(); Looper.loop(); 創(chuàng)建消息隊(duì)列并開啟循環(huán)茵典。使用HandlerThread.getLooper()創(chuàng)建Handler湘换,通過Handler發(fā)送消息/Runnable,Runnable被加入到隊(duì)列中,然后Looper取出Runnable執(zhí)行彩倚。這里主要是通過Handler切換到了子線程铐望,也就是HandlerThread的線程,所以可以執(zhí)行耗時(shí)任務(wù)愉耙。在這個(gè)Looper里面不是rr執(zhí)行僧叉,而是順序串行執(zhí)行。
HandlerThread handlerThread = new HandlerThread();
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper());
handler.sendMessage(new Runnable());
handlerThread.quit();

三哥谷、IntentService

IntentService是能執(zhí)行耗時(shí)任務(wù)的Service岸夯,它具有Service的高優(yōu)先級,可以執(zhí)行一些高優(yōu)先級的后臺任務(wù)们妥。
IntentService就是如上面猜扮,在onCreate中生成了HandlerThread和Handler。
在onStartCommand中监婶,調(diào)用了onStart旅赢,Handler發(fā)送消息到消息隊(duì)列,Handler在handlerMessage中回調(diào)onHandleIntent(Intent)惑惶,在onHandleIntent已經(jīng)是子線程煮盼,可以執(zhí)行耗時(shí)任務(wù),然后stopSelf()集惋。通常的Handler在處理消息時(shí)是在ui線程執(zhí)行孕似,這里因?yàn)橛玫氖荋andlerThread的Looper生成的Handler,所以切換到了HandlerThread這個(gè)子線程中去執(zhí)行耗時(shí)任務(wù)刮刑。
每執(zhí)行一個(gè)任務(wù)就啟動(dòng)一次onStartCommand喉祭。
public class MyIntentService extends IntentService
{
private final static String TAG = "main";
private String url_path="http://ww2.sinaimg.cn/bmiddle/9dc6852bjw1e8gk397jt9j20c8085dg6.jpg";
public MyIntentService()
{
super("IntentSer");
}
@Override
public void onCreate()
{
super.onCreate();
}

 @Override
 public int onStartCommand(Intent intent, int flags, int startId) 

{
return super.onStartCommand(intent, flags, startId);
}

@Override
 public void onDestroy() 

{
super.onDestroy();
}

 @Override
 protected void onHandleIntent(Intent intent) 

{
try {
// 在設(shè)備應(yīng)用目錄下創(chuàng)建一個(gè)文件
File file=new File(this.getFilesDir(), "weibo.jpg");
FileOutputStream fos=new FileOutputStream(file);
// 獲取網(wǎng)絡(luò)圖片的輸入流
InputStream inputStream = new URL(url_path).openStream();
// 把網(wǎng)絡(luò)圖片輸入流寫入文件的輸出流中
byte[] date=new byte[1024];
int len=-1;
while((len=inputStream.read(date))!=-1)
{
fos.write(date, 0, len);
}

         fos.close();
         inputStream.close();    
         Log.i(TAG, "The file download is complete");
     } catch (MalformedURLException e) 

{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
}
}

四、FAQ

最后附兩個(gè)常見的小問題出現(xiàn)的原因雷绢。
1.在非UI線程中更新UI原因
ViewRootImpl類中的checkThread()方法用于檢測當(dāng)前是否UI線程泛烙,如果不是就會(huì)引發(fā)CalledFromWrongThreadException。而ViewRootImpl是在onResume結(jié)束后才創(chuàng)建完成翘紊。如果在onResume執(zhí)行完成前蔽氨,比如onStart、onCreate中子線程執(zhí)行完畢帆疟,并修改了UI鹉究,此時(shí)View沒有繪制出來,相當(dāng)于設(shè)置了UI的一些屬性踪宠,最終也不會(huì)調(diào)用checkThread方法自赔,便不會(huì)報(bào)錯(cuò)。如果在onResume之后柳琢,比如延時(shí)幾秒鐘绍妨,ViewRootImpl已經(jīng)創(chuàng)建完成润脸,就會(huì)引發(fā)checkThread方法,從而報(bào)錯(cuò)他去。

2.在子線程正確更新UI
Activity.runOnUiThread(Runnable)
View.post(Runnable)
View.postDelayed(Runnable,long)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末毙驯,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子灾测,更是在濱河造成了極大的恐慌爆价,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件行施,死亡現(xiàn)場離奇詭異允坚,居然都是意外死亡魂那,警方通過查閱死者的電腦和手機(jī)蛾号,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來涯雅,“玉大人鲜结,你說我怎么就攤上這事』钅妫” “怎么了精刷?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蔗候。 經(jīng)常有香客問我怒允,道長,這世上最難降的妖魔是什么锈遥? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任纫事,我火速辦了婚禮,結(jié)果婚禮上所灸,老公的妹妹穿的比我還像新娘丽惶。我一直安慰自己,他們只是感情好爬立,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布钾唬。 她就那樣靜靜地躺著,像睡著了一般侠驯。 火紅的嫁衣襯著肌膚如雪抡秆。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天吟策,我揣著相機(jī)與錄音儒士,去河邊找鬼。 笑死踊挠,一個(gè)胖子當(dāng)著我的面吹牛乍桂,可吹牛的內(nèi)容都是我干的冲杀。 我是一名探鬼主播,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼睹酌,長吁一口氣:“原來是場噩夢啊……” “哼权谁!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起憋沿,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤旺芽,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后辐啄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體采章,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年壶辜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了悯舟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,117評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡砸民,死狀恐怖抵怎,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情岭参,我是刑警寧澤反惕,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站演侯,受9級特大地震影響姿染,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜秒际,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一悬赏、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧程癌,春花似錦舷嗡、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至锐峭,卻和暖如春中鼠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背沿癞。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工援雇, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人椎扬。 一個(gè)月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓惫搏,卻偏偏與公主長得像具温,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子筐赔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內(nèi)容