這是一道可能經常被問的面試題,首先先說一下NSRunloop。
- NSRunloop是一個消息循環(huán),會監(jiān)測輸入源(inputsource)和定時源(timer source)。apple官方文檔(多線程編程指南)描述: "run loop 是用來在線程上管理事件異步到達的基礎設施......run loop在沒有任何事件處理的時候會把它的線程置于休眠狀態(tài),它消除了消耗CPU周期輪詢,并防止處理器本身進入休眠狀態(tài)并節(jié)省電源。"消除CPU空轉是它最大的作用。
Runloop的重點是:
1.用來監(jiān)聽長耗時異步事件,例如網絡回調,蘋果原生和第三方用的都是Runloop。
2.消除CPU空轉。 - 每個線程都有一個默認的NSRunloop,主線程中的NSRunloop默認是運行的,非主線程中的NSRunloop默認是沒有運行的,通常需要為NSRunloop添加一個事件然后去運行。一般情況下沒有必要去啟動一個線程的NSRunloop,除非需要長久的去監(jiān)測某個異步事件。舉個具體的例子,NSURLConnection網絡數據請求,默認是異步的方式,其創(chuàng)建原理就是創(chuàng)建之后將其作為事件源加入當前的Runloop,而等待網絡響應的過程是在一個新建的獨立的線程中完成,當這個線程處理到某個階段比如收到響應后便通知之前的線程去執(zhí)行相應的delegate方法。
下面說說Runloop與autorelease的關系
- 對于每一個runloop,Entry事件(即將進入Loop),其回調內會調用 _objc_autoreleasePoolPush() 創(chuàng)建自動釋放池,這樣所有的AutoreleasePool會構成一個像CallStact一樣的棧式結構,在每一個Runloop結束時,Exit(即將退出Loop)調用_objc_autoreleasePoolPop() ,當前棧頂的AutoreleasePool會被銷毀,這樣這個Pool里面的每個object都有被release。