iOS多线程之NSOperation

本文深入探讨NSOperation在iOS开发中的应用,包括其基类、执行方式、使用实例及配置方法,着重介绍如何实现并发操作与依赖管理。

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任务。
  1. MyOperation *operation = [MyOperation alloc] init];  
  2. NSOperationQueue* aQueue = [[NSOperationQueue alloc] init];  
  3. [aQueue addOperation:operation];  
我们也可以直接通过NSOpeartion的start方法来处理operation任务,这样执行的话任务的处理是在start调用的线程中同步执行的。
  1. MyOperation *operation = [MyOperation alloc] init];  
  2. [operation start];  
isConcurrent 属性返回的就是operation要执行的任务相对于调用start的线程是同步的还是异步的, isConcurrent 默认返回NO。当然我们也可以自己创建线程来执行NSOperation的start方法达到并发执行的效果。

3.NSInvocationOperation的使用

  1. @implementation MyCustomClass  
  2. - (NSOperation*)taskWithData:(id)data   
  3. {  
  4.     NSInvocationOperation* theOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(myTaskMethod:) object:data];  
  5.    return theOp;  
  6. }  
  7. // This is the method that does the actual work of the task.  
  8. - (void)myTaskMethod:(id)data   
  9. {  
  10.     // Perform the task.  
  11. }  
  12. @end  

4.NSBlockOperation的使用

  1. NSBlockOperation* theOp = [NSBlockOperation blockOperationWithBlock: ^  
  2. {  
  3.     NSLog(@"Beginning operation.\n");  
  4.     // Do some work.  
  5. }];  
NSBlockOperation可以通过addExecutionBlock:方法添加多个block,只有所有block都执行完成的时候,operation才算是完成。

5.自定义NSOperation

NSOperation提供了一个基本结构,具体相关的并发执行的方法、operation依赖、KVO通知和取消操作还是需要我们自己实现的。整个NSOperation子类实现如下:
  1. @interface MyOperation : NSOperation {  
  2.     BOOL        executing;  
  3.     BOOL        finished;  
  4. }  
  5. - (void)completeOperation;  
  6. @end  
  7. @implementation MyOperation  
  8. - (id)init {  
  9.     self = [super init];  
  10.     if (self) {  
  11.         executing = NO;  
  12.         finished = NO;  
  13.     }  
  14.     return self;  
  15. }  
  16. - (void)start {  
  17.     // Always check for cancellation before launching the task.  
  18.     if ([self isCancelled])  
  19.     {  
  20.         // Must move the operation to the finished state if it is canceled.  
  21.         [self willChangeValueForKey:@"isFinished"];  
  22.         finished = YES;  
  23.         [self didChangeValueForKey:@"isFinished"];  
  24.         return;  
  25.     }  
  26.     // If the operation is not canceled, begin executing the task.  
  27.     [self willChangeValueForKey:@"isExecuting"];  
  28.     [self main];  
  29.     executing = YES;  
  30.     [self didChangeValueForKey:@"isExecuting"];  
  31. }  
  32. - (void)main {  
  33.     @autoreleasepool {  
  34.         BOOL isDone = NO;  
  35.         while (![self isCancelled] && !isDone) {  
  36.             // Do some work and set isDone to YES when finished  
  37.         }  
  38.         [self completeOperation];  
  39.    }  
  40. }  
  41. - (void)completeOperation {  
  42.     [self willChangeValueForKey:@"isFinished"];  
  43.     [self willChangeValueForKey:@"isExecuting"];  
  44.     executing = NO;  
  45.     finished = YES;  
  46.     [self didChangeValueForKey:@"isExecuting"];  
  47.     [self didChangeValueForKey:@"isFinished"];  
  48. }  
  49. - (void)cancel {  
  50.     [super cancel];  
  51.     //取消网络请求      
  52. }  
  53. - (BOOL)isConcurrent {  
  54.     return YES;  
  55. }  
  56. - (BOOL)isExecuting {  
  57.     return executing;  
  58. }  
  59. - (BOOL)isFinished {  
  60.     return finished;  
  61. }  
  62. @end  
并发operation需要实现以下方法:
  • start
  • main
  • isConcurrent
  • isExecuting
  • isFinished
NSOperation支持KVO的属性有:
  • isCancelled
  • isConcurrent
  • isExecuting
  • isFinished
  • isReady
  • dependencies
  • queuePriority
  • completionBlock
不是所有的属性都要我们发送KVO通知,如果我们覆盖了start方法,就要像上面的代码一样在适当的地方发出isExecuting和isFinished的通知。如果我们实现了自己的addDependency:或者removeDependency:,就要适当的地方发送dependencies的通知。

6.配置NSOperation

6.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方法执行期间有效,其他方法都是按照默认优先级执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值