每個程式至少運行於一個thread中(稱為main thread),你可以認為每個thread是一個獨立的處理器,每個都並行的運行著。Thread是用來為在同一個進程中並行的執行多處代碼。
如果你的應用程式只有一個thread,則這個thread需要完成這個應用的所有事情。它必需對事件進行響應,更新應用程式視窗以及完成應用結果的所有運算。這樣的話問題就來了,只有一個thread且它同一時間只能做一件事,如果你的應用程式有一個運算需要很長的時間那會發生什麼呢?你的代碼在忙於運算其需要的結果,你的應用程式則停止了對使用者事件響應和更新視窗。如果這個運算進行了很長時間,則使用者可能會認為應用程式已失去了響應並將其關閉。如果你將運算移到另一個thread中,則main
thread則只用於事件響應和更新視窗。這就是為什麼不應該在main thread中運行有時間持續消耗(堵塞)的代碼。
一個在新thread中運行函數的方法:
[NSThread detachNewThreadSelector:@selector(theSelector) toTarget:self withObject:nil];
如果你有一些使用者介面或者其它的代碼需要對事件進行監聽(如網路介面),你則要使用到run loop。每個thread會建立其自己的run loop,通常我們並不需要關心這些。Run loop同時也負責autorelease pool的建立和釋放。
對於每個建立的thread都需要為其建立一個autorelease pool,如果有一個方法調用detachNewThreadSelector,則需要使用如下的autorelease pool相應的代碼將其包含在內:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];[code here][pool release];
Run loop(CFRunLoop)是一個事件處理迴圈,你可以用來安排工作並協調你所收到的事件。使用run loop的目的是保持你的thread當有事件處理時處於忙狀態併當沒有事件處理時進入休眠。
Run loop是一組架構用來管理thread中收到的非同步訊息。Run loop運行時對thread中的一個或多個事件來源進行監控。當事件到達時,系統將thread喚醒並將事件發送給run loop,然後run loop將事件再次轉寄給你所指定的處理函數。如果沒有收到事件或事件處理完成後,run loop將thread設定為休眠。你可以不為你所建立的thread設定run loop,但設定了將為使用者提供很好的體驗。Run
loop為建立長時間運行且消耗少量資源的thread提供了可能。因為run loop將其所屬thread設定為休眠狀態如果沒有事件收到。要對run loop進行配置,你所要做的是建立你的thread,獲得對run loop對象的引用,安裝你的事件處理器並運行run loop。Cocoa為你在main thread中自動設定了run loop,如果你要建立另一個長時間啟動並執行thread,則你必須自己對run loop進行配置。
Run loop就像它的名字一樣,是你thread中的一個迴圈並對收到的事件進行處理。你的代碼提供控制語句用來對run loop進行執行——換句話說:你的代碼提供while或for迴圈來驅動run loop。在你的迴圈中,你使用run loop對象來“運行”事件處理代碼。事件處理代碼主要進行接收事件並呼叫事件處理函數。
Run loop從兩個不同的事件來源中接收訊息。Input sources(CFRunLoopSource)投遞非同步訊息,通常來自於另一個thread或另一個應用程式。Timer sources(CFRunLoopTimer)當在計劃的時間或重複的時間間隔內投遞同步訊息。兩種事件來源都使用應用程式指定的處理方式對到達的事件進行處理。展示了run loop和不同的事件來源結構。
Input sources投遞非同步訊息至對應的處理器並導致退出runUnitDate:方法(該方法在將run loop與thread關聯時調用)的執行。Timer sources投遞同步訊息至對應的處理器但並不導致run loop退出。為了能對input sources進行額外處理,run loops也能根據run loop的行為產生相應的通知。註冊run loop observers(CFRunLoopObserver)可以接收到這些通知並使用它們在thread上進行額外的處理。
你的應用程式不需要建立或顯示的管理NSRunLoop對象。每一個NSThread對象,包括應用程式的main Thread都會自動建立一個NSRunLoop對象。如果你需要訪問當前thread的run loop,你可以使用NSRunLoop對象的類方法currentRunLoop。
Timer(定時器)也是通過run loop進行處理。與run loop進行比較,你通常在你的程式中直接使用Timer。
建立一個timer的最簡單方法:
[self performSelector:@selector(aSelector) withObject:nil afterDelay:1.0];
有些情況下你也可能建立自己的NSTimer對象,從而可以自己對Timer進行釋放和重用。