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];