iOS多執行緒的初步研究(三)-- NSRunLoop
弄清楚NSRunLoop確實需要花時間,這個類的概念和模式似乎是Apple的平臺獨有(iOS+MacOSX),很難徹底搞懂(iOS沒開源,嗚嗚)。
官網的解釋是說run loop可以用於處理非同步事件,很抽象的說法。不羅嗦,先看看NSRunLoop幾個常用的方法。
+ (NSRunLoop *)currentRunLoop; //獲得當前執行緒的run loop
+ (NSRunLoop *)mainRunLoop; //獲得主執行緒的run loop
- (void)run; //進入處理事件迴圈,如果沒有事件則立刻返回。注意:主執行緒上呼叫這個方法會導致無法返回(進入無限迴圈,雖然不會阻塞主執行緒),因為主執行緒一般總是會有事件處理。
- (void)runUntilDate:(NSDate *)limitDate; //同run方法,增加超時引數limitDate,避免進入無限迴圈。使用在UI執行緒(亦即主執行緒)上,可以達到暫停的效果。
- (BOOL)runMode:(NSString *)mode beforeDate:(NSDate *)limitDate; //等待訊息處理,好比在PC終端視窗上等待鍵盤輸入。一旦有合適事件(mode相當於定義了事件的型別)被處理了,則立刻返回;類同run方法,如果沒有事件處理也立刻返回;有否事件處理由返回布林值判斷。同樣limitDate為超時引數。
- (void)acceptInputForMode:(NSString *)mode beforeDate:(NSDate *)limitDate; //似乎和runMode:差不多(測試過是這種結果,但確定是否有其它特殊情況下的不同),沒有BOOL返回值。
官網文件也提到run和runUntilDate:會以NSDefaultRunLoopMode引數呼叫runMode:來處理事件。
當app執行後,iOS系統已經幫助主執行緒啟動一個run loop,而一般執行緒則需要手動來啟動run loop。
使用run loop的一個好處就是避免執行緒輪詢的開銷,run loop在無事件處理時可以自動進入睡眠狀態,降低CPU的能耗。
比如一般執行緒輪詢的方式為:
while (condition)
{
// waiting for new data
sleep(1);
// process current data
}
其實這種方式是很能消耗CPU時間片的,如果在UI執行緒中這樣使用還會阻塞UI響應。而改用NSRunLoop來實現,則可大大改善執行緒的執行效率,而且不會阻塞UI(很神奇,呵呵。有點像javascript,用單執行緒實現多執行緒的效果)。上面的例子可以改為:
while (condition)
{
// waiting for new data
if ([[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]])
{
// process current data
}
}
接下來我們看看具體的例子,包括如何實現執行緒執行的關聯同步(join),以及UI執行緒run loop的一般使用技巧等。
假設有個執行緒A,它會啟動執行緒B,然後等待B執行緒的結束。NSThread是沒有join的方法,用run loop方式實現就比較精巧。
NSThread *A; //global
A = [[NSThread alloc] initWithTarget:self selector:@selector(runA) object:nil]; //生成執行緒A
[A start]; //啟動執行緒A
- (void)runA
{
[NSThread detachNewThreadSelector:@selector(runB) toTarget:self withObject:nil]; //生成執行緒B
while (1)
{
if ([[NSRunLoop currentRunLoop] runMode:@"CustomRunLoopMode" beforeDate:[NSDate distantFuture]]) //相當於join
{
NSLog(@"執行緒B結束");
break;
}
}
}
- (void)runB
{
sleep(1);
[self performSelector:@selector(setData) onThread:A withObject:nil waitUntilDone:YES modes:@[@"CustomRunLoopMode"]];
}
實際執行時,過1秒後執行緒A也會自動結束。這裡用到自定義的mode,一般在UI執行緒上呼叫run loop會使用預設的mode。結合while迴圈,UI執行緒就可以實現子執行緒的同步執行(具體例子這裡不再描述,可參看:http://www.cnblogs.com/tangbinblog/archive/2012/12/07/2807088.html)。
下面羅列呼叫主執行緒的run loop的各種方式,讀者可以加深理解:
[[NSRunLoop mainRunLoop] run]; //主執行緒永遠等待,但讓出主執行緒時間片
[[NSRunLoop mainRunLoop] runUntilDate:[NSDate distantFuture]]; //等同上面呼叫
[[NSRunLoop mainRunLoop] runUntilDate:[NSDate date]]; //立即返回
[[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10.0]]; //主執行緒等待,但讓出主執行緒時間片,然後過10秒後返回
[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate: [NSDate distantFuture]]; //主執行緒等待,但讓出主執行緒時間片;有事件到達就返回,比如點選UI等。
[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate: [NSDate date]]; //立即返回
[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate: [NSDate dateWithTimeIntervalSinceNow:10.0]]; //主執行緒等待,但讓出主執行緒時間片;有事件到達就返回,如果沒有則過10秒返回。
相關文章
- iOS多執行緒的初步研究(九)-- dispatch源iOS執行緒
- iOS多執行緒的初步研究(四)-- NSTimeriOS執行緒
- 多執行緒學習初步(轉)執行緒
- 對webWorker多執行緒效能的初步探索Web執行緒
- IOS多執行緒iOS執行緒
- iOS 多執行緒iOS執行緒
- iOS 多執行緒之執行緒安全iOS執行緒
- iOS多執行緒之執行緒安全iOS執行緒
- iOS多執行緒的使用iOS執行緒
- 多執行緒(三)執行緒
- C#中的執行緒(三)多執行緒C#執行緒
- iOS多執行緒整理iOS執行緒
- iOS-多執行緒iOS執行緒
- java基礎-多執行緒初步瞭解Java執行緒
- iOS多執行緒安全-13種執行緒鎖?iOS執行緒
- [iOS] 談談iOS多執行緒的鎖iOS執行緒
- iOS 多執行緒總結iOS執行緒
- iOS多執行緒GCD篇iOS執行緒GC
- iOS 多執行緒筆記iOS執行緒筆記
- IOS多執行緒之(GCD)iOS執行緒GC
- iOS 多執行緒之GCDiOS執行緒GC
- iOS 多執行緒介紹iOS執行緒
- iOS 多執行緒-學習iOS執行緒
- iOS多執行緒--NSThreadiOS執行緒thread
- iOS 多執行緒詳解iOS執行緒
- iOS 深入剖析多執行緒iOS執行緒
- iOS多執行緒調研iOS執行緒
- IOS下使用多執行緒iOS執行緒
- IOS 多執行緒技術iOS執行緒
- iOS多執行緒程式設計三:Operation和OperationQueueiOS執行緒程式設計
- 多執行緒系列(三):執行緒池基礎執行緒
- iOS多執行緒的那些事兒iOS執行緒
- iOS 開發中的多執行緒iOS執行緒
- Java多執行緒(三):SynchronizedJava執行緒synchronized
- 多執行緒筆記 三執行緒筆記
- iOS多執行緒程式設計:執行緒同步總結iOS執行緒程式設計
- 執行緒和程式基礎以及多執行緒的基本使用(iOS)執行緒iOS
- iOS多執行緒:GCD詳解iOS執行緒GC