iOS多線程梳理-NSOperation

上一篇 iOS多線程梳理-GCD(3)

NSOperation

NSOperation 是蘋果公司對 GCD 的封裝,面向?qū)ο蟆?NSOperation 和 NSOperationQueue 分別對應(yīng) GCD 的 任務(wù) 和 隊列 。使用如下:
1.將要執(zhí)行的任務(wù)封裝到一個 NSOperation 對象中
2.將此任務(wù)添加到一個 NSOperationQueue 對象中

添加任務(wù)

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

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

NSBlockOperation 還有一個方法:addExecutionBlock: ,通過這個方法可以給 Operation 添加多個執(zhí)行 Block,并且addExecutionBlock添加的Block 會并發(fā)異步執(zhí)行。如下:

    NSLog(@"beagin %@",[NSThread currentThread]);
    NSBlockOperation *blockOp = [NSBlockOperation blockOperationWithBlock:^{//當(dāng)前線程
       sleep(2);
        NSLog(@"first %@",[NSThread currentThread]);
    }];
    for (NSInteger i=0; i<3; i++) {
        [blockOp addExecutionBlock:^{//其他線程
            sleep(2);
            NSLog(@"section %@",[NSThread currentThread]);
        }];
    }
    [blockOp start];
/*輸出結(jié)果:
     2017-10-12 17:15:30.638732+0800 GCDLearnAdvanced[5362:776321] beagin <NSThread: 0x608000076000>{number = 1, name = main}
     2017-10-12 17:15:32.640445+0800 GCDLearnAdvanced[5362:776360] section <NSThread: 0x60c000466e40>{number = 5, name = (null)}
     2017-10-12 17:15:32.640444+0800 GCDLearnAdvanced[5362:776363] section <NSThread: 0x60c000467a00>{number = 3, name = (null)}
     2017-10-12 17:15:32.640445+0800 GCDLearnAdvanced[5362:776361] section <NSThread: 0x600000270a00>{number = 4, name = (null)}
     2017-10-12 17:15:32.640469+0800 GCDLearnAdvanced[5362:776321] first <NSThread: 0x608000076000>{number = 1, name = main}
*/

創(chuàng)建隊列NSOperation

  • 主隊列

    NSOperationQueue *mQueue = [NSOperationQueue mainQueue];
    
  • 其他隊列
    因為主隊列比較特殊,所以會單獨有一個類方法來獲得主隊列。那么通過初始化產(chǎn)生的隊列就是其他隊列了

  • 串行隊列
    NSOperationQueue 有一個參數(shù) maxConcurrentOperationCount 最大并發(fā)數(shù),可以用來設(shè)置最多可以讓多少個任務(wù)同時執(zhí)行。當(dāng)把它設(shè)置為 1 的時候,就是為串行隊列

任務(wù)依賴案例:

    //有 3 個任務(wù):A: 從服務(wù)器上下載一張圖片,B:給這張圖片加個水印,C:把圖片返回給服務(wù)器
    //1.任務(wù)一:下載圖片
    NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"下載圖片 - %@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:1.0];
    }];
    //2.任務(wù)二:打水印
    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"打水印   - %@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:1.0];
    }];
    //3.任務(wù)三:上傳圖片
    NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"上傳圖片 - %@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:1.0];
    }];
    //4.設(shè)置依賴
    [operation2 addDependency:operation1];      //任務(wù)二依賴任務(wù)一
    [operation3 addDependency:operation2];      //任務(wù)三依賴任務(wù)二
    //5.創(chuàng)建隊列并加入任務(wù)
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue addOperations:@[operation3, operation2, operation1] waitUntilFinished:YES];
    NSLog(@"其他task");
/*輸出結(jié)果:
2017-10-12 17:33:27.035147+0800 GCDLearnAdvanced[5494:803023] 下載圖片 - <NSThread: 0x600000274dc0>{number = 3, name = (null)}
2017-10-12 17:33:28.039947+0800 GCDLearnAdvanced[5494:803025] 打水印   - <NSThread: 0x60c000266e80>{number = 4, name = (null)}
2017-10-12 17:33:29.043323+0800 GCDLearnAdvanced[5494:803025] 上傳圖片 - <NSThread: 0x60c000266e80>{number = 4, name = (null)}
2017-10-12 17:33:30.048417+0800 GCDLearnAdvanced[5494:802986] 其他task
*/
  • 不能相互依賴,比如A依賴B,B依賴A,這樣會死鎖
  • 可以使用 removeDependency 來解除依賴關(guān)系
  • addOperations:waitUntilFinished:當(dāng)傳入YES時會阻塞,等待任務(wù)完畢后才會繼續(xù)往下執(zhí)行

指定并發(fā)數(shù)量的多任務(wù)執(zhí)行案例:

    NSLog(@"beagin %@",[NSThread currentThread]);
    NSOperationQueue *operationQ = [[NSOperationQueue alloc]init];
    operationQ.maxConcurrentOperationCount = 2;
    for (NSInteger i=0; i<5; i++) {
        NSBlockOperation *blockOp = [[NSBlockOperation alloc]init];
        [blockOp addExecutionBlock:^{
            sleep(2);
            NSLog(@"first%@ %@",@(i),[NSThread currentThread]);
        }];
        [operationQ addOperation:blockOp];
    }
/*輸出結(jié)果:
     2017-10-12 16:55:18.363146+0800 GCDLearnAdvanced[5194:730174] beagin <NSThread: 0x60c00006ed40>{number = 1, name = main}
     2017-10-12 16:55:20.364293+0800 GCDLearnAdvanced[5194:730224] first0 <NSThread: 0x60400007f700>{number = 3, name = (null)}
     2017-10-12 16:55:20.364293+0800 GCDLearnAdvanced[5194:730228] first1 <NSThread: 0x6080002722c0>{number = 4, name = (null)}
     2017-10-12 16:55:22.368552+0800 GCDLearnAdvanced[5194:730225] first2 <NSThread: 0x600000269a00>{number = 5, name = (null)}
     2017-10-12 16:55:22.368552+0800 GCDLearnAdvanced[5194:730221] first3 <NSThread: 0x60400007d880>{number = 6, name = (null)}
     2017-10-12 16:55:24.372538+0800 GCDLearnAdvanced[5194:730228] first4 <NSThread: 0x6080002722c0>{number = 4, name = (null)}
*/

通過打印的時間我們可以看到最多只有兩條線程同時異步執(zhí)行。

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

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

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