一:什么是線程
線程(Thread)是操作系統(tǒng)能夠進(jìn)行運算調(diào)度的最小單位。它被包含在進(jìn)程之中,是進(jìn)程中的實際運作單位。一條線程指的是進(jìn)程中一個單一順序的控制流,一個進(jìn)程中可以并發(fā)多個線程,每個線程并行執(zhí)行不同的任務(wù)。
二:線程的分類
Android中的線程分為主線程和子線程,主線程主要處理和界面相關(guān)的事情,而子線程一般用于耗時操作。由于Android的特性,如果主線程中執(zhí)行耗時操作那么就會導(dǎo)致程序無法及時響應(yīng),因此耗時操作必須放在子線程中執(zhí)行。
主線程是指進(jìn)程所擁有的線程,在java中默認(rèn)情況下一個進(jìn)程只有一個線程,這個線程就是主線程。除了主線程以外都是子線程。
主線程的作用是運行四大組件以及處理他們和用戶的交互。
子線程的作用是執(zhí)行耗時任務(wù),比如網(wǎng)路請求,I/O操作等。
三:Android中的線程形態(tài)
除了Thread本身外,在Android中可以扮演線程角色的還有很多,比如AsyncTask、IntentService和HandlerThread。盡管他們表現(xiàn)形式有別于傳統(tǒng)線程,但是他們的本質(zhì)仍然是傳統(tǒng)的線程。
AsyncTask它的底層用到了線程池,IntentService和HandlerThread來說,它們底層直接使用了線程。
AsycnTask封裝了線程池和Handler,它主要是為了方便開發(fā)者在子線程中更新UI。
HandlerThread是一種具有消息循環(huán)的線程,在它的內(nèi)部可以使用Handler。
IntentService是一個服務(wù),系統(tǒng)對其進(jìn)行了封裝,可以方便執(zhí)行后臺任務(wù),IntentService內(nèi)部采用HandlerThread來執(zhí)行任務(wù),當(dāng)任務(wù)執(zhí)行完畢后IntentService會自動退出。從任務(wù)的角度看,IntentService很像一個后臺線程,但是IntentService是一種服務(wù),它不容易被系統(tǒng)殺死從而盡可能保證任務(wù)的執(zhí)行,而如果是一個后臺線程,由于沒有活動的四大組件,那么這個進(jìn)程的優(yōu)先級會非常低,容易被系統(tǒng)殺死,這就是IntentService的優(yōu)點。
四:AsyncTask和它的工作原理
AsyncTask是一種輕量級的異步任務(wù)類,它可以在線程池中執(zhí)行后臺任務(wù),然后把執(zhí)行的進(jìn)度和最終結(jié)果傳遞給主線程并在主線程中更新UI。但AsyncTask并不合適進(jìn)行特別耗時的后臺任務(wù),對于特別耗時的任務(wù)來說,建議使用線程池。
AsyncTask是一個抽象的泛型類,提供了Params.Progress和Result三個泛型參數(shù),Params表示參數(shù)的類型,Progress表示后臺任務(wù)的執(zhí)行進(jìn)度的類型,Result表示后臺任務(wù)的返回結(jié)果的類型,如果AsyncTask確實不需要傳遞具體的參數(shù),那么這三個泛型參數(shù)可以用void來代替。
public abstract class AsyncTask<Params,Progress,Result>
AsyncTask提供了4個核心方法,他們的含義如下
(1)onPreExecute()在主線程中執(zhí)行,在異步任務(wù)執(zhí)行之前,此方法會被調(diào)用,一般用于做一些準(zhǔn)備工作。
(2)doInBackground(Params...params)在線程池中執(zhí)行,此方法用于執(zhí)行異步任務(wù),params參數(shù)表示異步任務(wù)的輸入?yún)?shù)。在此方法中可以通過publishProgress方法來更新任務(wù)的進(jìn)度,publishProgress方法會調(diào)用onProgressUpdate方法。另外此方法需要返回計算結(jié)果onPostExecute方法。
(3)onProgressUpdate(Progress...values)在主線程中執(zhí)行,當(dāng)后臺任務(wù)的執(zhí)行進(jìn)度發(fā)生改變時此方法會被調(diào)用。
(4)onPostExecute(Result result)在主線程中執(zhí)行,在異步任務(wù)執(zhí)行之后,此方法會被調(diào)用,其中result參數(shù)是后臺任務(wù)的返回值,即doInBackground的返回值。
這幾個方法onPreExecute先執(zhí)行,接著是doInBackground最后才是onPostExecute。出了以上4個方法外,AsyncTask還提供了onCancelled()方法,它同樣在主線程執(zhí)行,當(dāng)異步任務(wù)被取消時,onCancelled()方法會被調(diào)用,這個時候onPostExecute則不會被調(diào)用。
AsyncTask在具體的使用過程中有一些條件限制,如下
(1)AsyncTask的類必須在主線程中加載,這就意味著第一次訪問AsyncTask必須發(fā)生在主線程,當(dāng)然在這個過程中Android4.1以上版本已經(jīng)被系統(tǒng)自動完成,在Android5.0的源碼中,可以查看ActivityThread的main方法,它會調(diào)用AsyncTask的init方法,這就滿足了AsyncTask的類必須在主線程中進(jìn)行加載這個條件了。
(2)AsyncTask的對象必須在主線程中創(chuàng)建。
(3)execute方法必須在UI線程調(diào)用。
(4)不要在程序中直接調(diào)用onPreExecute()、onPostExecute、doInBackground和onProgressUpdate方法。
(5)一個AsyncTask對象只能執(zhí)行一次,即只能調(diào)用一次execute方法,否則會報運行時異常。
(6)在Android1.6之前,AsyncTask是串行執(zhí)行任務(wù)的,Android1.6的時候AsyncTask開始采用線程池里處理并行任務(wù)。但從Android3.0開始,為了避免AsyncTask所帶來的并發(fā)錯誤,又采用一個線程來串行執(zhí)行任務(wù)。但是在Android3.0以后,仍然可以通過AsyncTask的executeOnExecutor方法來并行執(zhí)行任務(wù)。
AsyncTask的工作原理

HandlerThread
繼承了Thread,它是一種可以使用Handler的Thread,它的實現(xiàn)也很簡單,就是在run方法中通過Looper.prepare()來創(chuàng)建消息隊列,并通過Looper.loop()來開啟消息循環(huán),這樣在實際的使用中就允許在HandlerThread中創(chuàng)建Handler了。
普通Thread主要用于在run方法中執(zhí)行一個耗時任務(wù),而HandlerThread在內(nèi)部創(chuàng)建了消息隊列,外界需要通過Handler的消息方式來通知HandlerThread執(zhí)行一個具體的任務(wù)。HandlerThread是一個很有用的類,它在Android中的一個具體的使用場景是IntentService,由于HandlerThread的run方法是一個無限循環(huán),因此當(dāng)明確不需要再使用HandlerThread時,可以通過它的quit或者quitSafely方法來終止線程 的執(zhí)行,這是一個良好的編程習(xí)慣。
IntentService
IntentService是一個特殊的Service,它繼承了Service并且它是一個抽象類,因此必須創(chuàng)建它的子類才能使用IntentService,它可以執(zhí)行后臺耗時任務(wù),當(dāng)任務(wù)執(zhí)行后它會自動停止,同時由于IntentService是服務(wù)的原因,它的優(yōu)先級比單純的線程要高很多,所以IntentService比較適合執(zhí)行一些高優(yōu)先級的后臺任務(wù),因為它優(yōu)先級高,不容易被系統(tǒng)殺死。IntentService封裝了HandlerThread和Handler.
IntentService被第一次啟動時,它的onCreate方法會被調(diào),onCreate方法會創(chuàng)建一個HandlerThread然后使用它的Looper來構(gòu)造一個Handler對象mServiceHandler,這樣通過mServiceHandler發(fā)送的消息最終都會在HandlerThread中執(zhí)行。IntentService可以用于執(zhí)行后臺任務(wù),每次啟動IntentService,它的onStartCommand方法就會調(diào)用一次,IntentService在onStartCommand中處理每個后臺任務(wù)的Intent。
IntentService會通過stopSelf(int startId)方法來嘗試停止服務(wù),而這個時候可能還有其他消息未處理,stopSlef(int startId)則會等待所有的消息都處理完畢后才終止服務(wù)。stopSlef(int startId)在嘗試停止服務(wù)之前會判斷最近啟動服務(wù)的次數(shù)是否和sartId相等,如果相等就立刻停止服務(wù),不相等則不停止服務(wù),這個策略可以從AMS的stopServiceToken方法的實現(xiàn)中找到依據(jù)。
IntentService的onHandleIntent方法是一個抽象方法,他需要我們在子類中實現(xiàn),它的作用是從Intent參數(shù)中區(qū)分具體的任務(wù)并執(zhí)行這些任務(wù)。如果目前只存在一個后臺任務(wù),那么onHandleIntent方法執(zhí)行完這個任務(wù)后,stopSelf(int startId)就會直接停止服務(wù),如果目前存在多個后臺任務(wù),那么當(dāng)onHandleIntent方法執(zhí)行完最后一個任務(wù)時,stopSelf(int startId)才會直接停止服務(wù),由于每執(zhí)行一個后臺任務(wù)就必須啟動一次IntentService,而IntentService內(nèi)部則通過消息的方式向HandlerThread請求執(zhí)行任務(wù),Handler中的Looper是順序處理消息的,這就意味著IntentService也是順序執(zhí)行后臺任務(wù)的,當(dāng)有多個后臺任務(wù)同時存在時,這些后臺任務(wù)會按照外界發(fā)起的順序排隊執(zhí)行。