了解下RunLoop

? run loop是線(xiàn)程的基礎(chǔ)即纲,是一個(gè)你用來(lái)安排工作低斋、協(xié)調(diào)事件接收的事件處理循環(huán)。run loop的目的是讓你的線(xiàn)程掘猿,有事件處理的時(shí)候保持活躍唇跨,無(wú)事件處理的時(shí)候保持休眠稠通,避免資源占用礁遵。run loop 實(shí)際上是一個(gè)對(duì)象,這個(gè)對(duì)象管理了其需要處理的事件和消息采记,并提供了一個(gè)入口函數(shù)來(lái)執(zhí)行Event Loop 的邏輯佣耐。線(xiàn)程執(zhí)行了這個(gè)函數(shù)后,就會(huì)一直處于這個(gè)函數(shù)內(nèi)部 “接受消息->等待->處理” 的循環(huán)中唧龄,直到這個(gè)循環(huán)結(jié)束(比如傳入 quit 的消息)兼砖,函數(shù)返回。一個(gè)run loop就是一個(gè)事件處理循環(huán)既棺,用來(lái)不停的監(jiān)聽(tīng)和處理輸入事件并將其分配到對(duì)應(yīng)的目標(biāo)上進(jìn)行處理讽挟。

????OSX/iOS 系統(tǒng)中丸冕,提供了兩個(gè)這樣的對(duì)象:NSRunLoop 和 CFRunLoopRef耽梅。CFRunLoopRef 是在 CoreFoundation 框架內(nèi)的,它提供了純 C 函數(shù)的 API胖烛,所有這些 API 都是線(xiàn)程安全的眼姐。NSRunLoop 是基于 CFRunLoopRef 的封裝,提供了面向?qū)ο蟮?API佩番,但是這些 API 不是線(xiàn)程安全的众旗。

????線(xiàn)程和 RunLoop 之間是一一對(duì)應(yīng)的,其關(guān)系是保存在一個(gè)全局的 Dictionary 里趟畏。線(xiàn)程剛創(chuàng)建時(shí)并沒(méi)有 RunLoop贡歧,如果你不主動(dòng)獲取,那它一直都不會(huì)有赋秀。RunLoop 的創(chuàng)建是發(fā)生在第一次獲取時(shí)利朵,RunLoop 的銷(xiāo)毀是發(fā)生在線(xiàn)程結(jié)束時(shí)。你只能在一個(gè)線(xiàn)程的內(nèi)部獲取其 RunLoop(主線(xiàn)程除外)猎莲。

系統(tǒng)默認(rèn)注冊(cè)了5個(gè)Mode:

(1)kCFRunLoopDefaultMode: App的默認(rèn) Mode绍弟,通常主線(xiàn)程是在這個(gè) Mode 下運(yùn)行的。

(2)UITrackingRunLoopMode: 界面跟蹤 Mode益眉,用于 ScrollView 追蹤觸摸滑動(dòng)晌柬,保證界面滑動(dòng)時(shí)不受其他 Mode 影響姥份。

(3)UIInitializationRunLoopMode: 在剛啟動(dòng) App 時(shí)第進(jìn)入的第一個(gè) Mode郭脂,啟動(dòng)完成后就不再使用。

(4)GSEventReceiveRunLoopMode: 接受系統(tǒng)事件的內(nèi)部 Mode澈歉,通常用不到展鸡。

(5)kCFRunLoopCommonModes: 這是一個(gè)占位的 Mode,沒(méi)有實(shí)際作用埃难。

Run Loop的四個(gè)作用:

(1)使程序一直運(yùn)行接受用戶(hù)輸入

(2)決定程序在何時(shí)應(yīng)該處理哪些Event

(3)調(diào)用解耦

(4)節(jié)省CPU時(shí)間

????主線(xiàn)程的run loop默認(rèn)是啟動(dòng)的莹弊。iOS的應(yīng)用程序里面涤久,程序啟動(dòng)后會(huì)有一個(gè)如下的main() 函數(shù)。

#import

#import "AppDelegate.h"

int main(intargc,char* argv[]) {

? ? @autoreleasepool {

? ? ? ? return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));

? ? }

}

UIApplicationMain() 函數(shù)忍弛,會(huì)為main thread 設(shè)置一個(gè)NSRunLoop 對(duì)象响迂,這就解釋了為什么我們的應(yīng)用可以在無(wú)人操作的時(shí)候休息,需要讓它干活的時(shí)候又能立馬響應(yīng)细疚。

什么時(shí)候使用run loop

????僅當(dāng)在為你的程序創(chuàng)建輔助線(xiàn)程的時(shí)候蔗彤,你才需要顯式運(yùn)行一個(gè)run loop。Run loop是程序主線(xiàn)程基礎(chǔ)設(shè)施的關(guān)鍵部分疯兼。所以然遏,Cocoa和Carbon程序提供了代碼運(yùn)行主程序的循環(huán)并自動(dòng)啟動(dòng)run loop。IOS程序中UIApplication的run方法(或Mac OS X中的NSApplication)作為程序啟動(dòng)步驟的一部分吧彪,它在程序正常啟動(dòng)的時(shí)候就會(huì)啟動(dòng)程序的主循環(huán)待侵。類(lèi)似的,RunApplicationEventLoop函數(shù)為Carbon程序啟動(dòng)主循環(huán)姨裸。如果你使用xcode提供的模板創(chuàng)建你的程序秧倾,那你永遠(yuǎn)不需要自己去顯式的調(diào)用這些例程。

對(duì)于輔助線(xiàn)程傀缩,你需要判斷一個(gè)run loop是否是必須的中狂。如果是必須的,那么你要自己配置并啟動(dòng)它扑毡。你不需要在任何情況下都去啟動(dòng)一個(gè)線(xiàn)程的run loop胃榕。比如,你使用線(xiàn)程來(lái)處理一個(gè)預(yù)先定義的長(zhǎng)時(shí)間運(yùn)行的任務(wù)時(shí)瞄摊,你應(yīng)該避免啟動(dòng)run loop勋又。Run loop在你要和線(xiàn)程有更多的交互時(shí)才需要,比如以下情況:

使用端口或自定義輸入源來(lái)和其他線(xiàn)程通信

使用線(xiàn)程的定時(shí)器

Cocoa中使用任何performSelector…的方法

使線(xiàn)程周期性工作

關(guān)注點(diǎn)

Cocoa中的NSRunLoop類(lèi)并不是線(xiàn)程安全的换帜。

我們不能再一個(gè)線(xiàn)程中去操作另外一個(gè)線(xiàn)程的run loop對(duì)象楔壤,那很可能會(huì)造成意想不到的后果。不過(guò)幸運(yùn)的是CoreFundation中的不透明類(lèi)CFRunLoopRef是線(xiàn)程安全的惯驼,而且兩種類(lèi)型的run loop完全可以混合使用蹲嚣。Cocoa中的NSRunLoop類(lèi)可以通過(guò)實(shí)例方法:

- (CFRunLoopRef)getCFRunLoop;

獲取對(duì)應(yīng)的CFRunLoopRef類(lèi),來(lái)達(dá)到線(xiàn)程安全的目的祟牲。

Run loop的管理并不完全是自動(dòng)的隙畜。

我們?nèi)员仨氃O(shè)計(jì)線(xiàn)程代碼以在適當(dāng)?shù)臅r(shí)候啟動(dòng)run loop并正確響應(yīng)輸入事件,當(dāng)然前提是線(xiàn)程中需要用到run loop说贝。而且议惰,我們還需要使用while/for語(yǔ)句來(lái)驅(qū)動(dòng)run loop能夠循環(huán)運(yùn)行,下面的代碼就成功驅(qū)動(dòng)了一個(gè)run loop:

BOOL?isRunning?=?NO;??

do???

{??

isRunning?=?[[NSRunLoop?currentRunLoop]?runMode:NSDefaultRunLoopMode?beforeDate:[NSDatedistantFuture]];??

}???

while?(isRunning);??

Run loop同時(shí)也負(fù)責(zé)autorelease pool的創(chuàng)建和釋放乡恕。

在使用手動(dòng)的內(nèi)存管理方式的項(xiàng)目中言询,會(huì)經(jīng)常用到很多自動(dòng)釋放的對(duì)象俯萎,如果這些對(duì)象不能夠被即時(shí)釋放掉,會(huì)造成內(nèi)存占用量急劇增大运杭。Run loop就為我們做了這樣的工作夫啊,每當(dāng)一個(gè)運(yùn)行循環(huán)結(jié)束的時(shí)候,它都會(huì)釋放一次autorelease pool辆憔,同時(shí)pool中的所有自動(dòng)釋放類(lèi)型變量都會(huì)被釋放掉涮母。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市躁愿,隨后出現(xiàn)的幾起案子叛本,更是在濱河造成了極大的恐慌,老刑警劉巖彤钟,帶你破解...
    沈念sama閱讀 217,907評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件来候,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡逸雹,警方通過(guò)查閱死者的電腦和手機(jī)营搅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)梆砸,“玉大人转质,你說(shuō)我怎么就攤上這事√溃” “怎么了休蟹?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,298評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)日矫。 經(jīng)常有香客問(wèn)我赂弓,道長(zhǎng),這世上最難降的妖魔是什么哪轿? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,586評(píng)論 1 293
  • 正文 為了忘掉前任盈魁,我火速辦了婚禮,結(jié)果婚禮上窃诉,老公的妹妹穿的比我還像新娘杨耙。我一直安慰自己,他們只是感情好飘痛,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布珊膜。 她就那樣靜靜地躺著,像睡著了一般敦冬。 火紅的嫁衣襯著肌膚如雪辅搬。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,488評(píng)論 1 302
  • 那天脖旱,我揣著相機(jī)與錄音堪遂,去河邊找鬼。 笑死萌庆,一個(gè)胖子當(dāng)著我的面吹牛溶褪,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播践险,決...
    沈念sama閱讀 40,275評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼猿妈,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了巍虫?” 一聲冷哼從身側(cè)響起彭则,我...
    開(kāi)封第一講書(shū)人閱讀 39,176評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎占遥,沒(méi)想到半個(gè)月后俯抖,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,619評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瓦胎,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評(píng)論 3 336
  • 正文 我和宋清朗相戀三年芬萍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片搔啊。...
    茶點(diǎn)故事閱讀 39,932評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡柬祠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出负芋,到底是詐尸還是另有隱情漫蛔,我是刑警寧澤,帶...
    沈念sama閱讀 35,655評(píng)論 5 346
  • 正文 年R本政府宣布旧蛾,位于F島的核電站惩猫,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏蚜点。R本人自食惡果不足惜轧房,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望绍绘。 院中可真熱鬧奶镶,春花似錦、人聲如沸陪拘。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,871評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)左刽。三九已至捺信,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背迄靠。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,994評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工秒咨, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人掌挚。 一個(gè)月前我還...
    沈念sama閱讀 48,095評(píng)論 3 370
  • 正文 我出身青樓雨席,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親吠式。 傳聞我的和親對(duì)象是個(gè)殘疾皇子陡厘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容