014-NSOperation多線程技術(shù)

NSOperation 是用 OC 語(yǔ)言對(duì) GCD 的封裝,面向?qū)ο?,使用?jiǎn)單,并且提供了一些額外的操作,比如取消任務(wù)、添加任務(wù)間依賴關(guān)系等,不需要關(guān)心線程和線程生命周期,自動(dòng)多線程執(zhí)行。

NSOperation 是一個(gè)抽象類,使用 NSOperation 有三種方法

  • NSInvocationOperation
  • NSBlockOperation
  • 自定義子類繼承 NSOperation

NSInvocationOperation

使用 NSInvocationOperation 需要自定義執(zhí)行函數(shù)

- (void)operationTestLearn
{
    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task:) object:@"task"];
    [operation start];
}

- (void)task:(NSString *)value
{
    NSLog(@"%@", value);
}

默認(rèn)情況下執(zhí)行 start 方法是在當(dāng)前線程同步執(zhí)行操作,如果要異步多線程執(zhí)行,則要用 NSOperationQueue。

    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task:) object:@"task"];
    NSOperationQueue *queue = [NSOperationQueue new];
    [queue addOperation:operation];

NSBlockOperation

NSBlockOperation 使用 block 作為需要執(zhí)行的操作。

    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"block task");
    }];
    [operation start];

單獨(dú)執(zhí)行一個(gè) block 是同步操作,但 NSBlockOperation 支持加入多個(gè) block,這樣就會(huì)進(jìn)行異步多線程執(zhí)行操作。

    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"block task1");
    }];
    
    [operation addExecutionBlock:^{
        NSLog(@"block task2");
    }];
    
    [operation addExecutionBlock:^{
        NSLog(@"block task3");
    }];
    
    [operation addExecutionBlock:^{
        NSLog(@"block task4");
    }];
    
    [operation start];

這里每一個(gè) block 都會(huì)在單獨(dú)一個(gè)線程內(nèi)執(zhí)行。

當(dāng)然也可以將 operation 放入隊(duì)列中執(zhí)行。

    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"block task1");
    }];
    
    [operation addExecutionBlock:^{
        NSLog(@"block task2");
    }];
    
    [operation addExecutionBlock:^{
        NSLog(@"block task3");
    }];
    
    [operation addExecutionBlock:^{
        NSLog(@"block task4");
    }];
    
    NSOperationQueue *queue = [NSOperationQueue new];
    [queue addOperation:operation];

NSOperationQueue 也有執(zhí)行在主線程的 main queue,是一個(gè)串行隊(duì)列

NSOperationQueue *queue = [NSOperationQueue mainQueue];

自定義 NSOperation

繼承 NSOperation,實(shí)現(xiàn)其中的 main 方法可以簡(jiǎn)單實(shí)現(xiàn)一個(gè) operation,當(dāng)然也可以復(fù)寫(xiě) start 方法,但是要手動(dòng)管理狀態(tài)

需要手動(dòng)管理的狀態(tài)有:

  • isExecuting 代表任務(wù)正在執(zhí)行中
  • isFinished 代表任務(wù)已經(jīng)執(zhí)行完成
  • isCancelled 代表任務(wù)已經(jīng)取消執(zhí)行

必須通過(guò) KVO 機(jī)制通知狀態(tài)轉(zhuǎn)移,由于 operation 支持 cancel,所以 isCancelled 用于檢查是否需要取消當(dāng)前操作。當(dāng)實(shí)現(xiàn)了start方法時(shí),默認(rèn)會(huì)執(zhí)行start方法,而不執(zhí)行main方法。

線程相關(guān)

隊(duì)列可以設(shè)置最大并發(fā)數(shù)

    NSLog(@"queue maxConcurrentOperationCount %ld", [queue maxConcurrentOperationCount]);
    [queue setMaxConcurrentOperationCount:4];

可以取消、暫?;蚧謴?fù)操作。

    [queue cancelAllOperations];
    [queue setSuspended:YES];

當(dāng)然 NSOperation 也可以單獨(dú)取消

    [operation cancel];

還可以對(duì) operation 添加依賴關(guān)系,這種關(guān)系可以跨線層依賴

    NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"block task1");
    }];
    
    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"block task2");
    }];
    
    [operation2 addDependency:operation1];
    
    NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"block task3");
    }];
    
    [operation3 addDependency:operation2];
    
    NSBlockOperation *operation4 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"block task4");
    }];
    
    [operation4 addDependency:operation3];
    
    NSOperationQueue *queue = [NSOperationQueue mainQueue];
    [queue addOperation:operation1];
    [queue addOperation:operation2];
    [queue addOperation:operation3];
    [queue addOperation:operation4];

但是依賴關(guān)系不能形成環(huán),否則都無(wú)法執(zhí)行。

如果想監(jiān)聽(tīng) operation 是否執(zhí)行完,也可以加上監(jiān)聽(tīng)

    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"running");
    }];
    
    [operation setCompletionBlock:^{
        NSLog(@"finished");
    }];
    
    NSOperationQueue *queue = [NSOperationQueue new];
    [queue addOperation:operation];
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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