線程池:
1.共有四種:Executors
newCachedThreadPool創(chuàng)建一個(gè)可緩存線程池埃叭,如果線程池長(zhǎng)度超過(guò)處理需要,可靈活回收空閑線程,若無(wú)可回收翎蹈,則新建線程走趋。
newFixedThreadPool 創(chuàng)建一個(gè)定長(zhǎng)線程池志衣,可控制線程最大并發(fā)數(shù)汹押,超出的線程會(huì)在隊(duì)列中等待矿筝。
newScheduledThreadPool 創(chuàng)建一個(gè)定長(zhǎng)線程池,支持定時(shí)及周期性任務(wù)執(zhí)行棚贾。
newSingleThreadExecutor 創(chuàng)建一個(gè)單線程化的線程池,它只會(huì)用唯一的工作線程來(lái)執(zhí)行任務(wù)榆综,保證所有任務(wù)按照指定順序(FIFO, LIFO, 優(yōu)先級(jí))執(zhí)行妙痹。
可以使用自己提供的 ThreadFactory 創(chuàng)建新線程。
上面幾個(gè)方法返回ExecutorService對(duì)象鼻疮。調(diào)用execute方法執(zhí)行任務(wù)怯伊。
2.改線程設(shè)置優(yōu)先級(jí):
a.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);在線程里的run方法中調(diào)用就行
b.調(diào)用線程的.setPriority();方法
把工作線程設(shè)置為后臺(tái)類型,防止搶占UI資源判沟。默認(rèn)的為Default耿芹,歸于default cgroup,會(huì)平等的和UI線程爭(zhēng)奪CPU資源挪哄。
3.AsyncTask的使用:線程優(yōu)先級(jí)為background吧秕,對(duì)UI線程的執(zhí)行影響極小。串行和并行和版本有關(guān)迹炼。
a.取消任務(wù):
我們可以隨時(shí)調(diào)用 cancel(boolean)去取消這個(gè)加載任務(wù)砸彬,調(diào)用這個(gè)方法會(huì)間接調(diào)用 iscancelled 并且返回true 颠毙。
當(dāng)調(diào)用cancel()后,在doInBackground()return后 我們將會(huì)調(diào)用onCancelled(Object) 不在調(diào)用onPostExecute(Object)
//注:但是doInBackground()方法會(huì)繼續(xù)執(zhí)行砂碉,只是不在調(diào)用onPostExecute
為了保證任務(wù)更快取消掉蛀蜜,你應(yīng)該在doInBackground()周期性的檢查iscancelled 去進(jìn)行判斷。
**注意增蹭,我們的oncancel和onPostExecute一樣滴某,都是在UI線程中執(zhí)行。滋迈。壮池。所以當(dāng)我們想要取消之后,有些界面變化 我們可以在oncancel里面改變UI.
某些情況下杀怠,我們調(diào)用cancel(true)可能就會(huì)失效
比如 :task已經(jīng)加載完成椰憋,或者 已經(jīng)取消過(guò)一次,或者是其他情況
4.線程池特點(diǎn):
Thread(),AsyncTask適合處理單個(gè)任務(wù)的場(chǎng)景赔退,HandlerThread適合串行處理多任務(wù)的場(chǎng)景橙依。當(dāng)需要并行的處理多任務(wù)之時(shí),ThreadPoolExecutor是更好的選擇硕旗。
線程池可以避免線程的頻繁創(chuàng)建和銷毀窗骑,顯然性能更好,
但線程池并發(fā)的特性往往也是疑難雜癥的源頭漆枚,是代碼降級(jí)和失控的開(kāi)始创译。多線程并行導(dǎo)致的bug往往是偶現(xiàn)的,不方便調(diào)試墙基,一旦出現(xiàn)就會(huì)耗掉大量的開(kāi)發(fā)精力软族。
5.IntentService
IntentService又是另一種開(kāi)工作線程的方式,從名字就可以看出這個(gè)工作線程會(huì)帶有service的屬性残制。和AsyncTask不同立砸,沒(méi)有和UI線程的交互,也不像HandlerThread的工作線程會(huì)一直存活初茶。
IntentService背后其實(shí)也有一個(gè)HandlerThread來(lái)串行的處理Message Queue颗祝,從IntentService的onCreate方法可以看出。
只不過(guò)在所有的Message處理完畢之后恼布,工作線程會(huì)自動(dòng)結(jié)束螺戳。所以可以把IntentService看做是Service和HandlerThread的結(jié)合體,適合需要在工作線程處理UI無(wú)關(guān)任務(wù)的場(chǎng)景折汞。
Android開(kāi)線程的方式雖然五花八門倔幼,但歸根到底最后還是映射到linux下的pthread,業(yè)務(wù)的設(shè)計(jì)還是脫不了和線程相關(guān)的基礎(chǔ)概念范疇:
線程的執(zhí)行順序字支,調(diào)度策略凤藏,生命周期奸忽,串行還是并行,同步還是異步等等揖庄。摸清楚各類API下線程的行為特點(diǎn)栗菜,在設(shè)計(jì)具體業(yè)務(wù)的線程模型的時(shí)候自然輕車熟路了,
線程模型的設(shè)計(jì)要有整個(gè)app視角的廣度蹄梢,切忌各業(yè)務(wù)模塊各玩各的疙筹。
6.HandlerThread
HandlerThread背后只有一個(gè)線程,所以任務(wù)是串行執(zhí)行的禁炒。串行相對(duì)于并行來(lái)說(shuō)更安全而咆,各任務(wù)之間不會(huì)存在多線程安全問(wèn)題。
HandlerThread所產(chǎn)生的線程會(huì)一直存活幕袱,Looper會(huì)在該線程中持續(xù)的檢查MessageQueue暴备。這一點(diǎn)和Thread(),AsyncTask都不同们豌,thread實(shí)例的重用可以避免線程相關(guān)的對(duì)象的頻繁重建和銷毀涯捻。
HandlerThread較之Thread(),AsyncTask需要寫(xiě)更多的代碼望迎,但在實(shí)用性障癌,靈活度,安全性上都有更好的表現(xiàn)辩尊。
使用步驟
盡管HandlerThread的文檔比較簡(jiǎn)單涛浙,但是它的使用并沒(méi)有想象的那么easy。
創(chuàng)建一個(gè)HandlerThread摄欲,即創(chuàng)建了一個(gè)包含Looper的線程轿亮。
HandlerThread handlerThread = new HandlerThread("123");
handlerThread.start(); //創(chuàng)建HandlerThread后一定要記得start()
獲取HandlerThread的Looper
Looper looper = handlerThread.getLooper();
創(chuàng)建Handler,通過(guò)Looper初始化
Handler handler = new Handler(looper);
通過(guò)以上三步我們就成功創(chuàng)建HandlerThread蒿涎。通過(guò)handler發(fā)送消息哀托,就會(huì)在子線程中執(zhí)行。
如果想讓HandlerThread退出劳秋,則需要調(diào)用handlerThread.quit();。
7.Timer和ScheduledExecutorService
優(yōu)先使用ScheduledExecutorService來(lái)做周期性定時(shí)任務(wù)胖齐。ScheduledExecutorService需要在生命周期方法中去處理玻淑,在頁(yè)面不可見(jiàn)時(shí)調(diào)用shutdownNow();shutdown;方法呀伙。