(转载)NSOperation and NSOperationQueue教程(翻译)
原文地址http://www.cimgf.com/2008/02/16/cocoa-tutorial-nsoperation-and-nsoperationqueue/
在任何一種語言里,線程都是一個難點,更糟糕的是,如果線程出了問題,往往會以一種非常糟糕的方式出現。因為這個,程序員要么竭力避免線程編程(將線程看作是魔鬼的種子),要么花費大量時間去確保所有線程代碼都運行良好。
幸運的是,Apple在OS X 10.5 leopard 有了很大的進步。NSThread類添加了很多非常有用的新方法,這些方法都使線程編程變得更加簡單。另外,Apple引入了兩個新的對象:NSOperation和NSOperationQueue。在這篇教程里,我將剖析一個簡單的例子來演示怎么來用這些新對象,以及他們怎樣在你的應用里加入多線程。
這里可以得到例子工程: Async Downloader Example Project
這篇教程,我將演示其中一種用NSOperation和NSOperationQueue處理一些適合后臺運行的任務的方法,這篇教程的目的是演示這些類的基本使用方法,但不是說只有這種唯一的方法使用他們。
如果你對java,或者它的變種熟悉的話,那么可以說,NSOperation 對象很像java.lang.Runnable接口。類似的,在java的Runnable接口中,NSOperation對象被設計為可以擴展的。還是和java一樣,這里也有一個方法可以被重載次數的最小值。對于NSOpetation來說,這個方法就是-(void)main.使用NSOperation的最簡單的一種方法是把它加入一個NSOperationQueue。一旦operation被加入了這個隊列,隊列就馬上把它踢出開始運行。operation運行結束后,隊列就馬上將它釋放。
NSOperation 例子
在這個例子里,我寫了一個NSOperation,在NSOperation里得到一個網頁,將這個網頁內容保存到一個字符串里,再把它解析到一個NSXMLDocument,然后再完成前,再把NSXMLDocument傳回到應用程序的主線程。
PageLoadOperation.h
#import <Cocoa/Cocoa.h>? @interface PageLoadOperation : NSOperation {NSURL *targetURL; } @property(retain) NSURL *targetURL;? - (id)initWithURL:(NSURL*)url;? @endPageLoadOperation.m
#import "PageLoadOperation.h" #import "AppDelegate.h"? @implementation PageLoadOperation? @synthesize targetURL;? - (id)initWithURL:(NSURL*)url; {if (![super init]) return nil;[self setTargetURL:url];return self; }? - (void)dealloc {[targetURL release], targetURL = nil;[super dealloc]; }? - (void)main {NSString *webpageString = [[[NSString alloc] initWithContentsOfURL:[self targetURL]] autorelease];NSError *error = nil;NSXMLDocument *document = [[NSXMLDocument alloc] initWithXMLString:webpageString options:NSXMLDocumentTidyHTML error:&error];if (!document) {NSLog(@"%s Error loading document (%@): %@", _cmd, [[self targetURL] absoluteString], error);return;} ?[[AppDelegate shared] performSelectorOnMainThread:@selector(pageLoaded:)withObject:documentwaitUntilDone:YES];[document release]; }? @end就像你看到的,這個類很簡單。在初始化方法里接受一個URL,并且保存起來。當main方法被調用的時候,用URL構造一個字符串,然后將這個字符串傳到NSXMLDocument的init方法。如果加載xml文檔沒有出錯,就把它傳回到AppDelegate,在主線程里,任務完成。當NSOperation的main方法結束,隊列將自動釋放對象。
AppDelegate.h
#import <Cocoa/Cocoa.h>? @interface AppDelegate : NSObject {NSOperationQueue *queue; }? + (id)shared; - (void)pageLoaded:(NSXMLDocument*)document;? @endAppDelegate.m
#import "AppDelegate.h" #import "PageLoadOperation.h"? @implementation AppDelegate static AppDelegate *shared; static NSArray *urlArray;? - (id)init {if (shared) {[self autorelease];return shared;}if (![super init]) return nil;?NSMutableArray *array = [[NSMutableArray alloc] init];[array addObject:@"http://www.google.com"];[array addObject:@"http://www.apple.com"];[array addObject:@"http://www.yahoo.com"];[array addObject:@"http://www.zarrastudios.com"];[array addObject:@"http://www.macosxhints.com"];urlArray = array;?queue = [[NSOperationQueue alloc] init];shared = self;return self; }? - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {for (NSString *urlString in urlArray) {NSURL *url = [NSURL URLWithString:urlString];PageLoadOperation *plo = [[PageLoadOperation alloc] initWithURL:url];[queue addOperation:plo];[plo release];} }? - (void)dealloc {[queue release], queue = nil;[super dealloc]; }? + (id)shared; {if (!shared) {[[AppDelegate alloc] init];}return shared; }? - (void)pageLoaded:(NSXMLDocument*)document; {NSLog(@"%s Do something with the XMLDocument: %@", _cmd, document); }? @end在這個示例AppDelegate里,有兩件事發生。第一,在init方法里,NSOperationQueue被初始化,并且有一組url被加載。然后,當應用程序完成了加載,applicationDidFinishLaunching:方法被NSApplication實例調用,AppDelegate在url上循環,為每一個url創建一個任務,并且把這些任務加入NSOperationQueue,一旦每一項加入了隊列,隊列就馬上彈出它賦給一個NSThread,線程將會運行opreation的main方法。一旦operation完成了,線程就馬上通知隊列,隊列就會釋放這個operation。
NSOperationQueue 同步
在這個非常簡單的例子里,加載足夠的對象頭查看他們同步運行事十分困難的。但是如果你執行的任務需要比這個花費更多的時間,你就會看到,隊列將同時運行所用的任務。幸運的是,如果你想設定同時可以運行的任務數量,你可以修改AppDelegate里的init方法:
- (id)init {if (shared) {[self autorelease];return shared;}if (![super init]) return nil;?NSMutableArray *array = [[NSMutableArray alloc] init];[array addObject:@"http://www.google.com"];[array addObject:@"http://www.apple.com"];[array addObject:@"http://www.yahoo.com"];[array addObject:@"http://www.zarrastudios.com"];[array addObject:@"http://www.macosxhints.com"];urlArray = array;queue = [[NSOperationQueue alloc] init];[queue setMaxConcurrentOperationCount:2];shared = self;return self; }在這個修改后的init方法里,隊列被限制到每次只有兩個操作可以同時運行。剩下的操作將不斷等待,直到前面的兩個操作完成,它們才有機會去運行。
結論
上面是NSOperation 和 NSOperationQueue使用中的基本形式。你會注意到,這個例子中的大部分代碼與創建和使用NSOperation 或者 NSOperationQueue毫無關系。實際編碼中需要用到的NSOperation很少,但是只要用這少量的代碼你就可以輕松的開始在你的應用程序中使用多線程,不但可以給用戶提供一份更好的體驗,而且可以更好的解決復雜的任務。
?
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的(转载)NSOperation and NSOperationQueue教程(翻译)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 点积的那个公式:a dot b =||a
- 下一篇: Linux下网络流量实时监控工具大全