原理本質(zhì):
線程局部空間里存儲(chǔ)的私有東西只可被當(dāng)前線程訪問戈抄。通過pthread_getspecific
,pthread_setspecific
進(jìn)行訪問, 通過Get Current Run Loop
本質(zhì)是到當(dāng)前線程的局部私有空間當(dāng)中去取已知關(guān)聯(lián)的runloop,沒有的就創(chuàng)建加載,實(shí)現(xiàn)常駐線程黔宛。這也說明Runloop與線程一一對應(yīng)的關(guān)系,子線程的Run loop默認(rèn)不會(huì)創(chuàng)建,獲取時(shí)候創(chuàng)建刮刑。
在runloop中通過preformSelect...onThread
給線程添加執(zhí)行任務(wù),當(dāng)不執(zhí)行的時(shí)候养渴,處于休眠雷绢,接收到觸發(fā)信號(hào)再次激活。使線程處于崩肀埃活狀態(tài)翘紊。
Runloopo的調(diào)用:
先去_CFTSDTable查找,如果存在直接獲取返回傻工;沒有找到霞溪,調(diào)用_CFRunloopGet0,內(nèi)部是_CFRunLoopCreat實(shí)現(xiàn)創(chuàng)建,創(chuàng)建完成存放入_CFTSDTable中中捆,并獲取返回鸯匹。
源碼里可以看到當(dāng)RunLoop中存在TimerSources,Input Sources時(shí)泄伪,才能保證子線程RunLoop不退出殴蓬。
Runloop優(yōu)雅的退出:
先添加觀察者之類的事件,在滿足要求情況下蟋滴,做操作:
1:移除port, (machport基于當(dāng)前系統(tǒng)消息隊(duì)列的一個(gè)端口染厅,收發(fā)當(dāng)前信息隊(duì)列),removePort
津函,但是這種方法不確保系統(tǒng)不會(huì)去添加一些額外的事件(例如timer肖粮,source)。
2:NSthread exit
,會(huì)導(dǎo)致runloop沒有退出尔苦,內(nèi)存泄漏涩馆,通過Instrument可以捕獲行施。
3:獲取當(dāng)前線程runloop,runloopStop
,同時(shí)添加時(shí)間結(jié)束標(biāo)識(shí)的變量,將runloop魂那,run的方法改為一個(gè)循環(huán)機(jī)制(while(變量&& runMode方式結(jié)合))來執(zhí)行runloop開啟和退出蛾号。
runmode:使用的是defaultMode模式,不能使用commonMode涯雅,如果是commonMode會(huì)返回RunLoopFinished鲜结,直接退出。
Runloop模式:
官方5中模式活逆,默認(rèn)模式精刷,UI模式等,在默認(rèn)模式下划乖,如果觸發(fā)timer事件贬养,會(huì)循環(huán)處理執(zhí)行timer事件,如果拖拽UI琴庵,UI模式下的source事件被觸發(fā)误算。UI模式的優(yōu)先級(jí)最高,默認(rèn)模式不執(zhí)行.
使用案例:
1:AutoreleasePool:在Runloop操作里注冊觀察者迷殿,觀測Runloop剛進(jìn)入儿礼,和Runloop即將進(jìn)入休眠狀態(tài)時(shí)來決定,當(dāng)前自動(dòng)釋放池的創(chuàng)建和釋放
2:core Animation:在Runloop操作里注冊觀察者庆寺,為了觀測runloop進(jìn)入before Waiting:時(shí)core Animation回調(diào)函數(shù)來進(jìn)行當(dāng)前的遍歷蚊夫,看界面是否有更新,有更新提交界面動(dòng)畫更新懦尝,RenderServer進(jìn)行渲染
3:主線程的卡頓檢測:在Runloop操作里注冊觀察者知纷,beforsource--beforwaiting之間的間隔時(shí)間。超時(shí)陵霉,可能就發(fā)生卡頓琅轧。
Mach Port如何進(jìn)行跨線程通訊?
一個(gè)thread執(zhí)行任務(wù)踊挠,通過port調(diào)用mach_msg(msg,MACH_SEND_MSG,··)
函數(shù)發(fā)送權(quán)限乍桂,消息由消息隊(duì)列去傳遞,里邊包含header效床,data睹酌,目的,size剩檀;另一線程擁有接收權(quán)限的不光有port憋沿,還有port set,port set允許單個(gè)線程等待來自多個(gè)端口的消息發(fā)送沪猴。只要port set 任何一個(gè)port調(diào)用mach_msg(msg,MACH_RCV_MSG,···)
函數(shù)接收到消息辐啄,那么此線程就會(huì)取消block甥绿。解除block,線程繼續(xù)往下執(zhí)行则披。