1.handler機(jī)制
使用:主線程創(chuàng)建Handler涮帘,復(fù)寫(xiě)handlemessage遂唧,子線程中sendmessage
Handler被創(chuàng)建時(shí),對(duì)類(lèi)中有final類(lèi)型的mlooper和mqueue的成員變量進(jìn)行初始化,looper通過(guò)Looper.mylooper方法柏锄,調(diào)用threadlocal.get獲取當(dāng)前線程,這樣就將handler和當(dāng)前線程進(jìn)行了綁定馏艾。然后mqueue就是looper的messagequeue他宛,這樣將messagequeue也進(jìn)行了綁定。
ps:Looper創(chuàng)建(prepare)的時(shí)候會(huì)在Threadlocal中若還沒(méi)有l(wèi)ooper换况,則會(huì)用set方法來(lái)保存唯一Looper职辨,在set的時(shí)候會(huì)create一個(gè)threadlocalmap,key是currentthread對(duì)象戈二,value是Looper的對(duì)象舒裤,以此將looper和threadLocal綁定。get的時(shí)候也是從map中去判斷是否已經(jīng)有Looper觉吭。
Looper.loop 一個(gè)for的死循環(huán),取queue的next進(jìn)行msg.target.dipatchMesage(msg),若無(wú)callback,則handlemessage, msg在入列enqueueMessage的時(shí)候msg.target=this和handler綁定.
loop為什么不會(huì)阻塞主線程, ?linux的epoll機(jī)制, 當(dāng)沒(méi)有消息的時(shí)候會(huì)epoll.wait腾供,等待句柄寫(xiě)的時(shí)候再喚醒,這個(gè)時(shí)候其實(shí)是阻塞的鲜滩。2伴鳖,所有的ui操作都通過(guò)handler來(lái)發(fā)消息操作。比如屏幕刷新16ms一個(gè)消息徙硅,你的各種點(diǎn)擊事件榜聂,所以就會(huì)有句柄寫(xiě)操作,喚醒上文的wait操作嗓蘑,所以不會(huì)被卡死了峻汉。
Epoll機(jī)制加事件驅(qū)動(dòng)模型,就是UI線程的本質(zhì)
Messagequeue本質(zhì)上就是massage的單鏈表,所以next方法就是msg的next. 使用message.obtain創(chuàng)建msg可以不用重復(fù)創(chuàng)建msg,減少jvm壓力
msg 延遲 處理時(shí)間以入列時(shí)間為準(zhǔn)
2 asynctask
它適合網(wǎng)絡(luò)請(qǐng)求或者簡(jiǎn)單數(shù)據(jù)處理脐往。但不適合處理特別耗時(shí)的后臺(tái)任務(wù)
?封裝了線程池和handler的異步框架,用來(lái)執(zhí)行異步任務(wù),方便在工作線程和子線程切換
?onpreExcute - doInBackGround耗時(shí)操作 - onpostExcute
在activity銷(xiāo)毀時(shí)應(yīng)該cancel asynctask,因?yàn)閠ask仍持有上個(gè)acitity的引用,會(huì)導(dǎo)致結(jié)果丟失
是串行synchronized的,可以并行,最多5個(gè)core線程,剩下的會(huì)排隊(duì)?
AsyncTask增加了一個(gè)新的接口executeOnExecutor休吠,這個(gè)接口允許開(kāi)發(fā)者提供自定義的線程池來(lái)運(yùn)行和調(diào)度Thread
AsyncTask的使用中會(huì)遇到三種泛型參數(shù):Params, Progress 和 Result
3 handlerThread
繼承了thread,內(nèi)有l(wèi)ooper對(duì)象,可以創(chuàng)建handler,可以在handleMessage中處理異步任務(wù)
不阻塞UI線程,但是不能進(jìn)行多任務(wù)處理,本質(zhì)是一個(gè)串行隊(duì)列
4 intentService
是service的抽象類(lèi),通過(guò)handler和handlerThread實(shí)現(xiàn)(內(nèi)部開(kāi)啟異步線程,可以做耗時(shí)操作),通過(guò)handlerthread獲取looper對(duì)象
是處理異步請(qǐng)求 的類(lèi),,任務(wù)執(zhí)行完成后會(huì)自動(dòng)停止. 可以啟動(dòng)多次,每一個(gè)耗時(shí)操作都會(huì)以工作隊(duì)列方式在IntentService的onHandleIntent
回調(diào)方法中執(zhí)行
啟動(dòng)多次實(shí)例只有一個(gè), 每次只執(zhí)行一個(gè)工作線程, 順序執(zhí)行,執(zhí)行完銷(xiāo)毀,可以通過(guò)stopself方法銷(xiāo)毀
不建議使用bindservice方法啟動(dòng),不然不會(huì)調(diào)用onhandleintent,那么就相當(dāng)于啟動(dòng)service
5 線程池 :
入隊(duì)順序 核心線程->workingqueue->非i核心線程
???? keepAliveTime:是非核心線程空閑時(shí)要等待下一個(gè)任務(wù)到來(lái)的時(shí)間
ArrayBlockingQueue :一個(gè)由數(shù)組結(jié)構(gòu)組成的有界阻塞隊(duì)列。在只有入隊(duì)高并發(fā)或出隊(duì)高并發(fā)的情況下业簿,因?yàn)椴僮鲾?shù)組瘤礁,且不需要擴(kuò)容,性能很高
LinkedBlockingQueue :一個(gè)由鏈表結(jié)構(gòu)組成的有界阻塞隊(duì)列梅尤。有兩把鎖,在入隊(duì)與出隊(duì)都高并發(fā)的情況下柜思,性能比ArrayBlockingQueue高很多
PriorityBlockingQueue :一個(gè)支持優(yōu)先級(jí)排序的無(wú)界阻塞隊(duì)列岩调。
DelayQueue:一個(gè)使用優(yōu)先級(jí)隊(duì)列實(shí)現(xiàn)的無(wú)界阻塞隊(duì)列。
SynchronousQueue:一個(gè)不存儲(chǔ)元素的阻塞隊(duì)列赡盘。
LinkedTransferQueue:一個(gè)由鏈表結(jié)構(gòu)組成的無(wú)界阻塞隊(duì)列号枕。
FixedThreadPool 只有核心線程?執(zhí)行長(zhǎng)期的任務(wù)
CachedThreadPool 只有非核心線程,等待時(shí)間60s?SynchronousQueue隊(duì)列,執(zhí)行很多短期異步任務(wù)?
SingleThreadPool單線程 ?一個(gè)任務(wù)一個(gè)任務(wù)執(zhí)行
NewScheduledThreadPool ?周期性執(zhí)行任務(wù)的場(chǎng)景
6.多進(jìn)程
好處
1、我們知道Android系統(tǒng)對(duì)每個(gè)應(yīng)用進(jìn)程的內(nèi)存占用是有限制的陨享,而且占用內(nèi)存越大的進(jìn)程葱淳,通常被系統(tǒng)殺死的可能性越大。讓一個(gè)組件運(yùn)行在單獨(dú)的進(jìn)程中抛姑,可以減少主進(jìn)程所占用的內(nèi)存赞厕,降低被系統(tǒng)殺死的概率。
2定硝、如果子進(jìn)程因?yàn)槟撤N原因崩潰了皿桑,不會(huì)直接導(dǎo)致主程序的崩潰,可以降低我們程序的崩潰率蔬啡。
3诲侮、即使主進(jìn)程退出了,我們的子進(jìn)程仍然可以繼續(xù)工作箱蟆,假設(shè)子進(jìn)程是推送服務(wù)浆西,在主進(jìn)程退出的情況下,仍然能夠保證用戶可以收到推送消息顽腾。
多進(jìn)程引發(fā)的問(wèn)題
靜態(tài)成員和單例模式失效
線程同步機(jī)制失效
SharedPreferences 可靠性降低
Application 被多次創(chuàng)建
AIDL:功能強(qiáng)大近零,支持進(jìn)程間一對(duì)多的實(shí)時(shí)并發(fā)通信,并可實(shí)現(xiàn) RPC (遠(yuǎn)程過(guò)程調(diào)用)抄肖。
Messenger:支持一對(duì)多的串行實(shí)時(shí)通信久信, AIDL 的簡(jiǎn)化版本。
Bundle:四大組件的進(jìn)程通信方式漓摩,只能傳輸 Bundle 支持的數(shù)據(jù)類(lèi)型裙士。
ContentProvider:強(qiáng)大的數(shù)據(jù)源訪問(wèn)支持,主要支持 CRUD 操作管毙,一對(duì)多的進(jìn)程間數(shù)據(jù)共享腿椎,例如我們的應(yīng)用訪問(wèn)系統(tǒng)的通訊錄數(shù)據(jù)。
BroadcastReceiver:即廣播夭咬,但只能單向通信啃炸,接收者只能被動(dòng)的接收消息。
文件共享:在非高并發(fā)情況下共享簡(jiǎn)單的數(shù)據(jù)卓舵。
Socket:通過(guò)網(wǎng)絡(luò)傳輸數(shù)據(jù)南用。
linux多進(jìn)程通信的方式
1.管道:管道的一端連接一個(gè)進(jìn)程的輸出。這個(gè)進(jìn)程會(huì)向管道中放入信息。管道的另一端連接一個(gè)進(jìn)程的輸入裹虫,這個(gè)進(jìn)程取出被放入管道的信息肿嘲。一個(gè)緩沖區(qū)不需要很大,它被設(shè)計(jì)成為環(huán)形的數(shù)據(jù)結(jié)構(gòu)以便管道可以被循環(huán)利用筑公。當(dāng)管道中沒(méi)有信息的話雳窟,從管道中讀取的進(jìn)程會(huì)等待,直到另一端的進(jìn)程放入信息匣屡。當(dāng)管道被放滿信息的時(shí)候封救,嘗試放入信息的進(jìn)程會(huì)等待,直到另一端的進(jìn)程取出信息耸采。當(dāng)兩個(gè)進(jìn)程都終結(jié)的時(shí)候兴泥,管道也自動(dòng)消失工育。
缺點(diǎn): 在創(chuàng)建時(shí)分配一個(gè)管道時(shí)虾宇,緩存區(qū)大小比較有限;并不適合Android大量的進(jìn)程通信
2.消息隊(duì)列:消息隊(duì)列提供了一種從一個(gè)進(jìn)程向另一個(gè)進(jìn)程發(fā)送一個(gè)數(shù)據(jù)塊的方法如绸。每個(gè)數(shù)據(jù)塊都被認(rèn)為含有一個(gè)類(lèi)型嘱朽,接收進(jìn)程可以獨(dú)立地接收含有不同類(lèi)型的數(shù)據(jù)結(jié)構(gòu)。我們可以通過(guò)發(fā)送消息來(lái)避免命名管道的同步和阻塞問(wèn)題怔接。但是消息隊(duì)列與命名管道一樣搪泳,每個(gè)數(shù)據(jù)塊都有一個(gè)最大長(zhǎng)度的限制。
缺點(diǎn): 信息復(fù)制兩次扼脐,額外的CPU消耗岸军;不合適頻繁或信息量大的通信;
3.共享內(nèi)存:什么是共享內(nèi)存:顧名思義瓦侮,共享內(nèi)存就是允許兩個(gè)不相關(guān)的進(jìn)程訪問(wèn)同一個(gè)邏輯內(nèi)存艰赞。共享內(nèi)存是在兩個(gè)正在運(yùn)行的進(jìn)程之間共享和傳遞數(shù)據(jù)的一種非常有效的方式。不同進(jìn)程之間共享的內(nèi)存通常安排為同一段物理內(nèi)存肚吏。進(jìn)程可以將同一段共享內(nèi)存連接到它們自己的地址空間中方妖,所有進(jìn)程都可以訪問(wèn)共享內(nèi)存中的地址無(wú)須復(fù)制,共享緩沖區(qū)直接付附加到進(jìn)程虛擬地址空間罚攀,速度快党觅;
缺點(diǎn): 通信需要設(shè)計(jì)復(fù)雜的機(jī)制保證各個(gè)進(jìn)程通訊有效性。進(jìn)程間的同步問(wèn)題操作系統(tǒng)無(wú)法實(shí)現(xiàn)斋泄,必須各進(jìn)程利用同步工具解決杯瞻;安全問(wèn)題比較突出,如果Android采用Binder 無(wú)異于將每個(gè)App放在一個(gè)內(nèi)存中炫掐,這樣是非常不安全的
4.套接字:作為更通用的接口又兵,傳輸效率低,主要用于不通機(jī)器或跨網(wǎng)絡(luò)的通信;
5.信號(hào)量:常作為一種鎖機(jī)制沛厨,防止某進(jìn)程正在訪問(wèn)共享資源時(shí)宙地,其他進(jìn)程也訪問(wèn)該資源。因此逆皮,主要作為進(jìn)程間以及同一進(jìn)程內(nèi)不同線程之間的同步手段宅粥。
6.信號(hào): 不適用于信息交換,更適用于進(jìn)程中斷控制电谣,比如非法內(nèi)存訪問(wèn)秽梅,殺死某個(gè)進(jìn)程等;接下來(lái)正面回答這個(gè)問(wèn)題剿牺,從5個(gè)角度來(lái)展開(kāi)對(duì)Binder的分析:
(1) 從性能的角度 數(shù)據(jù)拷貝次數(shù):Binder數(shù)據(jù)拷貝只需要一次企垦,而管道、消息隊(duì)列晒来、Socket都需要2次钞诡,但共享內(nèi)存方式一次內(nèi)存拷貝都不需要;從性能角度看湃崩,Binder性能僅次于共享內(nèi)存荧降。
(2) 從穩(wěn)定性的角度:Binder是基于C/S架構(gòu)的,Server端與Client端相對(duì)獨(dú)立攒读,穩(wěn)定性較好朵诫;而共享內(nèi)存實(shí)現(xiàn)方式復(fù)雜,沒(méi)有客戶與服務(wù)端之別薄扁, 需要充分考慮到訪問(wèn)臨界資源的并發(fā)同步問(wèn)題剪返,否則可能會(huì)出現(xiàn)死鎖等問(wèn)題;從這穩(wěn)定性角度看邓梅,Binder架構(gòu)優(yōu)越于共享內(nèi)存脱盲。僅僅從以上兩點(diǎn),各有優(yōu)劣震放,還不足以支撐google去采用binder的IPC機(jī)制宾毒,那么更重要的原因是:
(3) 從安全的角度:傳統(tǒng)Linux IPC的接收方無(wú)法獲得對(duì)方進(jìn)程可靠的UID/PID,從而無(wú)法鑒別對(duì)方身份殿遂;而Android作為一個(gè)開(kāi)放的開(kāi)源體系诈铛,擁有非常多的開(kāi)發(fā)平臺(tái),App來(lái)源甚廣墨礁,因此手機(jī)的安全顯得額外重要幢竹;對(duì)于普通用戶,絕不希望從App商店下載偷窺隱射數(shù)據(jù)恩静、后臺(tái)造成手機(jī)耗電等等問(wèn)題焕毫,傳統(tǒng)Linux IPC無(wú)任何保護(hù)措施蹲坷,完全由上層協(xié)議來(lái)確保。Android為每個(gè)安裝好的應(yīng)用程序分配了自己的UID邑飒,故進(jìn)程的UID是鑒別進(jìn)程身份的重要標(biāo)志循签,前面提到C/S架構(gòu),Android系統(tǒng)中對(duì)外只暴露Client端疙咸,Client端將任務(wù)發(fā)送給Server端县匠,Server端會(huì)根據(jù)權(quán)限控制策略,判斷UID/PID是否滿足訪問(wèn)權(quán)限撒轮,目前權(quán)限控制很多時(shí)候是通過(guò)彈出權(quán)限詢問(wèn)對(duì)話框乞旦,讓用戶選擇是否運(yùn)行。