1.NSOperation的理解NSOperation本身是一個抽象的基類,我們要自己子類化NSOpeartion並封裝我們要完成的任務,系統提供了兩個比較方便的子類NSInvocationOperation和NSBlockOperation,NSInvocationOperation方便我們以現有的方法來初始化一個operation,NSBlockOperation是方便我們從Block來初始化operation。所有的NSOperation都有如下特徵:
支援NSOperation對象之間建立依賴關係,當一個operation的所有依賴的operation都執行完了自己才會執行。支援可選的completion block,當operation的主任務完成之後調用。支援通過KVO通知來監控operation的執行狀態。支援指定operaion的優先順序來安排operation的相對指向順序。支援operation的取消操作來停止operation執行。2.NSOperation的執行通常情況下我們要並發執行的話只要簡單的把operation添加到operation queue中就行,operation queue負責建立線程並發地執行operation任務。
MyOperation *operation = [MyOperation alloc] init];NSOperationQueue* aQueue = [[NSOperationQueue alloc] init];[aQueue addOperation:operation];
我們也可以直接通過NSOpeartion的start方法來處理operation任務,這樣執行的話任務的處理是在start調用的線程中同步執行的。
MyOperation *operation = [MyOperation alloc] init];[operation start];
isConcurrent屬性返回的就是operation要執行的任務相對於調用start的線程是同步的還是非同步,isConcurrent預設返回NO。當然我們也可以自己建立線程來執行NSOperation的start方法達到並發執行的效果。
3.NSInvocationOperation的使用
@implementation MyCustomClass- (NSOperation*)taskWithData:(id)data { NSInvocationOperation* theOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(myTaskMethod:) object:data]; return theOp;}// This is the method that does the actual work of the task.- (void)myTaskMethod:(id)data { // Perform the task.}@end4.NSBlockOperation的使用
NSBlockOperation* theOp = [NSBlockOperation blockOperationWithBlock: ^{ NSLog(@"Beginning operation.\n"); // Do some work.}];NSBlockOperation可以通過addExecutionBlock:方法添加多個block,只有所有block都執行完成的時候,operation才算是完成。
5.自訂NSOperationNSOperation提供了一個基本結構,具體相關的並發執行的方法、operation依賴、KVO通知和取消操作還是需要我們自己實現的。整個NSOperation子類實現如下:
@interface MyOperation : NSOperation { BOOL executing; BOOL finished;}- (void)completeOperation;@end@implementation MyOperation- (id)init { self = [super init]; if (self) { executing = NO; finished = NO; } return self;}- (void)start { // Always check for cancellation before launching the task. if ([self isCancelled]) { // Must move the operation to the finished state if it is canceled. [self willChangeValueForKey:@"isFinished"]; finished = YES; [self didChangeValueForKey:@"isFinished"]; return; } // If the operation is not canceled, begin executing the task. [self willChangeValueForKey:@"isExecuting"]; [self main]; executing = YES; [self didChangeValueForKey:@"isExecuting"];}- (void)main { @autoreleasepool { BOOL isDone = NO; while (![self isCancelled] && !isDone) { // Do some work and set isDone to YES when finished } [self completeOperation]; }}- (void)completeOperation { [self willChangeValueForKey:@"isFinished"]; [self willChangeValueForKey:@"isExecuting"]; executing = NO; finished = YES; [self didChangeValueForKey:@"isExecuting"]; [self didChangeValueForKey:@"isFinished"];}- (void)cancel { [super cancel]; //取消網路請求 }- (BOOL)isConcurrent { return YES;}- (BOOL)isExecuting { return executing;}- (BOOL)isFinished { return finished;}@end並發operation需要實現以下方法:
startmainisConcurrentisExecutingisFinishedNSOperation支援KVO的屬性有:
isCancelledisConcurrentisExecutingisFinishedisReadydependenciesqueuePrioritycompletionBlock不是所有的屬性都要我們發送KVO通知,如果我們覆蓋了start方法,就要像上面的代碼一樣在適當的地方發出isExecuting和isFinished的通知。如果我們實現了自己的addDependency:或者removeDependency:,就要適當的地方發送dependencies的通知。
6.配置NSOperation6.1依賴管理我們可以通過addDependency:給當前operation添加依賴operation,依賴關係不限於operation是否在一個隊列裡。注意我們不要自己產生循環相依性,這樣會造成死結。
6.2優先順序管理在隊列裡的operation的執行順序取決於operation的狀態(是否準備就緒)和相對優先順序。是否準備就緒取決於operation的依賴operation是否完成,執行隊列會優先考慮operation,如果高優先順序的operation沒有準備就緒,執行隊列就會先執行低優先順序的operation。operation的相對優先順序只針對同一隊列,就是說一個低優先順序的operation可能比另一個隊列裡高優先順序的operation優先執行。
6.3底層線程優先順序管理
我們可以通過setThreadPriority:設定operation系統層級的線程優先順序,優先順序由0.0到1.0浮點數指定,預設是0.5。我們自己設定的系統層級的線程優先順序只針對main方法執行期間有效,其他方法都是按照預設優先順序執行。
參考連結:Concurrency Programming Guide