image.png
主線程與子線程
- 主線程:主線程主要處理UI交互纠脾,需要在任何時(shí)候都有較高的響應(yīng)速度亿傅,否則界面會(huì)產(chǎn)生卡頓。主線程中不能執(zhí)行耗時(shí)任務(wù)淤年,否則會(huì)出現(xiàn)ANR钧敞。主要作用是運(yùn)行四大組件,處理它們和用戶的交互
- 子線程:也叫工作線程麸粮,除主線程以外的線程都叫子線程溉苛。主要用來處理耗時(shí)任務(wù),如網(wǎng)絡(luò)請求弄诲、I/O愚战。
Android中的線程形態(tài)
Android中除了傳統(tǒng)的Thread之外,還包含了AsyncTask威根、HandlerThread以及IntentService凤巨,這三者底層實(shí)現(xiàn)也是Thread,但它們有特殊的形態(tài)和各自的優(yōu)缺點(diǎn)洛搀。
- AsyncTask
- 一種輕量級(jí)的異步任務(wù)類敢茁,可以在線程池中執(zhí)行后臺(tái)任務(wù),然后把進(jìn)度和結(jié)果傳遞給主線程留美,并在主線程中更新UI彰檬。AsyncTask內(nèi)部封裝了Thread和Handler。
- AsyncTask是一個(gè)抽象泛型類谎砾,提供了三個(gè)參數(shù)Params逢倍、Progress和Result,Params表示參數(shù)景图,Progress表示后臺(tái)任務(wù)執(zhí)行的進(jìn)度類型较雕,Result表示返回結(jié)果的類型。
public abstract class AsyncTask<Params, Progress, Result>
- 四個(gè)核心方法:
onPreExecute
=異步任務(wù)執(zhí)行之前調(diào)用挚币,可做一些準(zhǔn)備工作(主線程)亮蒋、doInBackground
=用于執(zhí)行異步任務(wù)(線程池),在此方法中調(diào)用publishProgress可以更新任務(wù)進(jìn)度,onProgressUpdate
=后臺(tái)任務(wù)進(jìn)度發(fā)生改變會(huì)調(diào)用(主線程)妆毕、onPostExecute
=異步任務(wù)執(zhí)行完成之后慎玖,該方法被調(diào)用(主線程) - 除了上面的四個(gè)方法,AsyncTask還提供了onCancelled方法(主線程)笛粘,異步任務(wù)取消時(shí)趁怔,onCancelled會(huì)被調(diào)用湿硝,這個(gè)時(shí)候onPostExecute不會(huì)被調(diào)用。
- AsyncTask使用過程中有幾個(gè)限制:AsyncTask必須在主線程中創(chuàng)建和加載润努,execute方法也要在主線程中調(diào)用关斜,execute方法只能調(diào)用一次,不然會(huì)報(bào)錯(cuò)任连。不要在程序中直接調(diào)用上面四個(gè)核心方法蚤吹。
- version < Android1.6:串行執(zhí)行任務(wù),Android1.6 <= version < Android3.0:采用線程池并行執(zhí)行任務(wù)随抠,version >= Android3.0:線程池串行執(zhí)行任務(wù)裁着,不過仍可通過executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, xxx)指定并發(fā)線程池來并行執(zhí)行任務(wù)。
- AsyncTask原理分析:1拱她、
AsyncTask的構(gòu)造方法
中會(huì)初始化一個(gè)sHandler:InternalHandler對象二驰,還會(huì)初始化一個(gè)mWorker:WorkerRunnable對象(執(zhí)行doInBackgroud,并且把結(jié)果發(fā)送個(gè)sHandler)秉沼,還有會(huì)用mWorker初始化mFuture:FutureTask對象(可取消桶雀、可查詢?nèi)蝿?wù)是否完成,可獲取任務(wù)結(jié)果)唬复。2矗积、execute方法
會(huì)默認(rèn)使用sDefaultExecute(串行線程池)來調(diào)用executeOnExecutor方法
,這個(gè)方法中會(huì)調(diào)用onPreExecute敞咧,并且會(huì)把mFuture作為一個(gè)Runnable(任務(wù))插入線程池的隊(duì)列mTask
棘捣。3、如果此時(shí)沒有active的AsyncTask任務(wù)休建,就會(huì)調(diào)用scheduleNext
來執(zhí)行隊(duì)列中的下一個(gè)AsyncTask乍恐,直到所有任務(wù)被執(zhí)行完為止。4测砂、mFuture任務(wù)執(zhí)行完成后會(huì)發(fā)送消息給sHandler對象
茵烈,sHandler處理消息時(shí)調(diào)用onPostExecute把結(jié)果傳遞給主線程處理
- HandlerThread
- 繼承自Thread,可以使用Handler的Thread
- 在run方法中通過Looper.prepare初始化Looper砌些,并且通過Looper.loop方法開啟消息循環(huán)呜投。這樣就允許在HandlerThread中使用Handler了。
- 普通Thread在run方法中執(zhí)行耗時(shí)任務(wù)存璃。而HandlerThread在run中開啟消息循環(huán)宙彪,外界需要通過Handler發(fā)送消息通知HandlerThread執(zhí)行一個(gè)具體任務(wù)。
- 由于HandlerThread方法中調(diào)用Looper.loop方法有巧,是一個(gè)死循環(huán),當(dāng)不需要再使用HandlerThread時(shí)悲没,通過quit或quitSafety方法終止線程執(zhí)行篮迎。
- IntentService
- 是一種特殊的Service男图,繼承Service的抽象類,抽象方法是onHandleIntent甜橱。正常的Service運(yùn)行在主線程逊笆,所以不能執(zhí)行耗時(shí)任務(wù),而IntentService的任務(wù)是放在HandlerThread中執(zhí)行岂傲,因此可以執(zhí)行耗時(shí)任務(wù)难裆。并且IntentService是四大組件,所以相對于一般線程來說镊掖,不易被系統(tǒng)殺死乃戈。
- 在onCreate方法中,創(chuàng)建一個(gè)HandlerThread線程亩进,然后用該線程的Looper構(gòu)造一個(gè)Handler(即該Handler是在HandlerThread線程中處理消息)症虑。
- 每次啟動(dòng)IntentService(startService),它的onStartCommand方法會(huì)被調(diào)用归薛,onStartCommand會(huì)調(diào)用onStart方法谍憔,onStart方法中會(huì)把Intent作為消息參數(shù),發(fā)送一個(gè)msg給Handler處理主籍,而Handler處理中會(huì)調(diào)用onHandleIntent方法(運(yùn)行在在HandlerThread線程中)习贫。
- Handler處理消息后還會(huì)調(diào)用stopSelf(msg.arg1)方法結(jié)束IntentService,如果目前只存在一個(gè)后臺(tái)任務(wù)千元,那么執(zhí)行完后stopSelf直接停止服務(wù)苫昌,如果有多個(gè)后臺(tái)任務(wù),那么當(dāng)onHandleIntent執(zhí)行完最后一個(gè)任務(wù)時(shí)诅炉,stopSelf才會(huì)停止服務(wù)蜡歹。
- onHandleIntent執(zhí)行多個(gè)后臺(tái)任務(wù),是按照外界發(fā)起的順序一次執(zhí)行涕烧。
Android中的線程池
- 線程池的優(yōu)點(diǎn)
- 可以復(fù)用線程池中的線程月而,減少創(chuàng)建和銷毀線程帶來的開銷
- 有效控制線程池中最大并發(fā)數(shù),避免線程之間相互搶占資源導(dǎo)致阻塞現(xiàn)象
- 對線程進(jìn)行管理议纯,提供定時(shí)和周期執(zhí)行功能
- ThreadPoolExecutor
ThreadPoolExecutor的繼承關(guān)系如下:
Executor interface
ExecutorService interface
AbstractExecutorService abstract class
ThreadPoolExecutor class
構(gòu)造方法如下:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
構(gòu)造方法中的參數(shù)解釋:
- corePoolSize:核心線程數(shù)父款,核心線程在線程池中能夠一直存活,及時(shí)處于閑置狀態(tài)瞻凤。除非把a(bǔ)llowCoreThreadTimeOut設(shè)置為true憨攒,那么當(dāng)核心線程閑置超過一定時(shí)間,就會(huì)被終止阀参。
- maximumPoolSize:線程池能容納的最大線程數(shù)肝集,當(dāng)線程數(shù)達(dá)到這個(gè)值,后續(xù)的任務(wù)將會(huì)被阻塞蛛壳。
- keepAliveTime:線程閑置超時(shí)時(shí)間杏瞻,正常情況下所刀,非核心線程閑置超過這個(gè)時(shí)間會(huì)被回收,當(dāng)設(shè)置了allowCoreThreadTimeOut捞挥,那么該參數(shù)對核心線程也生效浮创。
- unit:keepAliveTime對應(yīng)的單位,TimeUnit中取值
- workQueue:線程池中的任務(wù)隊(duì)列砌函,通過線程池的execute方法提交的Runnable都會(huì)存儲(chǔ)在此斩披。
- threadFactory:線程工廠,為線程池提供創(chuàng)建線程的功能讹俊,是個(gè)接口垦沉,只有一個(gè)方法:
Thread newThread(Runnable r)
。 - handler:不常用參數(shù)劣像,是
RejectedExecutionHandler
類型乡话,當(dāng)線程池?zé)o法執(zhí)行新任務(wù)時(shí)(任務(wù)隊(duì)列已滿),這是會(huì)調(diào)用handler的rejectedExecution來通知調(diào)用者耳奕,默認(rèn)情況會(huì)拋出一個(gè)異常RejectedExecutionException
绑青。
ThreadPoolExecutor執(zhí)行邏輯如下:
1. 線程池線程數(shù)量未達(dá)到核心線程數(shù),直接啟動(dòng)核心線程執(zhí)行任務(wù)
2. 如果達(dá)到或超過核心線程數(shù)屋群,會(huì)插到任務(wù)對隊(duì)列中排隊(duì)等待執(zhí)行
3. 任務(wù)隊(duì)列已滿闸婴,如果線程數(shù)量未達(dá)到最大線程數(shù),則會(huì)啟動(dòng)非核心線程執(zhí)行任務(wù)
4. 如果達(dá)到最大線程數(shù)芍躏,就會(huì)拒絕新任務(wù)邪乍,會(huì)調(diào)用RejectedExecutionHandler的rejectedExecution來通知調(diào)用者
- 線程池分類
主要介紹四種常見的線程池,都直接或間接配置ThreadPoolExecutor實(shí)現(xiàn)自己的功能对竣。
- FixedThreadPool:線程數(shù)量固定庇楞,都是核心線程,任務(wù)隊(duì)列無限大否纬。線程不會(huì)被回收吕晌,能夠快速響應(yīng)外界請求
- CachedThreadPool:都是非核心線程,并且非核心線程數(shù)量無上限临燃,閑置超時(shí)時(shí)間為60秒睛驳,任務(wù)隊(duì)列為空集合,所有任務(wù)都能立刻執(zhí)行膜廊。所有線程處于閑置狀態(tài)時(shí)乏沸,就會(huì)出現(xiàn)線程池內(nèi)無線程的情況。
- ScheduledThreadPool:核心線程固定爪瓜,非核心線程無上限蹬跃,主要用來執(zhí)行定時(shí)任務(wù)和周期任務(wù)。
- SingleThreadExecutor:只有一個(gè)核心線程铆铆,所有任務(wù)在核心線程中順序執(zhí)行蝶缀,不需要處理線程同步問題辆苔。
總結(jié)
本文主要介紹了Android中線程存在形式,還有線程池的分類和使用扼劈。希望對大家有幫助。