NSOperation和NSOperationQueue

概述

NSOperation 是蘋果公司對 GCD 的封裝,完全面向?qū)ο?,所以使用起來更好理解?大家可以看到 NSOperation 和 NSOperationQueue 分別對應 GCD 的 任務隊列 。
操作步驟主要就兩步:

  • 將要執(zhí)行的任務封裝到NSOperation中;
  • 將此任務添加到NSOperationQueue中。

添加任務

NSOperation 只是一個抽象類,所以不能封裝任務。但它有 2 個子類用于封裝任務。分別是:NSInvocationOperationNSBlockOperation 。創(chuàng)建一個 Operation 后,需要調(diào)用 start 方法來啟動任務,它會 默認在當前隊列同步執(zhí)行。當然你也可以在中途取消一個任務,只需要調(diào)用其 cancel 方法即可。

  • NSInvocationOperation :初始化
    //1.創(chuàng)建NSInvocationOperation對象
    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];
    
    //2.開始執(zhí)行
    [operation start];
    
- NSBlockOperation: 初始化

//1.創(chuàng)建NSBlockOperation對象
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"%@", [NSThread currentThread]);
}];
//2.開始任務
[operation start];

> 這樣添加的任務,會默認在當前線程執(zhí)行。不過```NSBlockOperation```提供了這個方法```addExecutionBlock:```,可以給operation添加多個block,這樣operation中的任務就會**并發(fā)執(zhí)行**,。他會在**主線程和其他多個線程**執(zhí)行這些任務

注:```addExecutionBlock``` 方法必須在 start() 方法之前執(zhí)行,否則就會報錯:

‘*** -[NSBlockOperation addExecutionBlock:]: blocks cannot be added after the operation has started executing or finished'


### 添加隊列
我們通過``` NSOperation``` 對象的``` start() ```方法來啟動這個任務,事實上系統(tǒng)默認是 **同步執(zhí)行** 的。就算是 ```addExecutionBlock``` 方法,也會在 **當前線程和其他線程 中執(zhí)行**,也就是說還是會占用當前線程。這時就要用到隊列 **NSOperationQueue** 了。一般分為兩種隊列:主隊列、其他隊列。**只要添加到隊列,會自動調(diào)用任務的 start() 方法**。
-  主隊列
通過調(diào)用```mainQueue```類方法創(chuàng)建的是為主隊列。

NSOperationQueue *queue = [NSOperationQueue mainQueue];

- 其他隊列
 因為主隊列比較特殊。個人覺得是主隊列是單例,所以統(tǒng)一用一個類方法來返回。通過初始化產(chǎn)生的隊列,就是其他隊列。其他隊列的任務會在其他線程并行執(zhí)行

//1.創(chuàng)建一個其他隊列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];

//2.創(chuàng)建NSBlockOperation對象
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"%@", [NSThread currentThread]);
}];

//3.添加多個Block
for (NSInteger i = 0; i < 5; i++) {
[operation addExecutionBlock:^{
NSLog(@"第%ld次:%@", i, [NSThread currentThread]);
}];
}

//4.隊列添加任務
[queue addOperation:operation];

#####需要注意
 運行上面代碼,會發(fā)現(xiàn)這里并沒有串行隊列,和GCD并不同。如果想要實現(xiàn),則可以設(shè)置```NSOperationQueue```中```maxConcurrentOperationCount```這個屬性。該屬性是設(shè)置最大并發(fā)數(shù),用來設(shè)置最多可以讓多少個任務同時執(zhí)行。因此設(shè)置為```1```即可。

```NSOperationQueue``` 還有一個快速添加任務的方法,```- (void)addOperationWithBlock:(void (^)(void))block;```這樣就可以添加一個任務到隊列中了,十分方便。

#### 依賴
 **場景**
 比如有 3 個任務:A: 從服務器上下載一張圖片,B:給這張圖片加個水印,C:把圖片返回給服務器。這時就可以用到依賴了

//1.任務一:下載圖片
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下載圖片 - %@", [NSThread currentThread]);
[NSThread sleepForTimeInterval:1.0];
}];

//2.任務二:打水印
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"打水印 - %@", [NSThread currentThread]);
[NSThread sleepForTimeInterval:1.0];
}];

//3.任務三:上傳圖片
NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"上傳圖片 - %@", [NSThread currentThread]);
[NSThread sleepForTimeInterval:1.0];
}];

//4.設(shè)置依賴
[operation2 addDependency:operation1]; //任務二依賴任務一
[operation3 addDependency:operation2]; //任務三依賴任務二

//5.創(chuàng)建隊列并加入任務
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperations:@[operation3, operation2, operation1] waitUntilFinished:NO];

使用注意:
 - 不能相互依賴, A依賴B,B依賴A,這樣會造成死鎖
 - 可以使用方法```removeDependency ```解除依賴
 - 依賴是添加到任務上的。因此,依賴是跨隊列的。

>  未完待續(xù)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容