iOS并发编程(二)——NSOperation

上一篇文章提到,利用NSThread可以实现多线程,但是线程的创建、维护和退出,都需要开发者自己负责,当线程较多时,这将很难管理。NSOperation是一个抽象类,封装了一个task,你不能直接实例化它。你可以手动管理Operation,也可以将其加入到NSOperationQueue中,加入到NSOperationQueue中的Operation不需要开发者去关注底层的多线程实现细节。

Cocoa提供了三种不同的NSOperation:

1. NSBlockOperation 

Block Operations提供了利用Block 对象来执行task的方法。

2. NSInvocationOperation

顾名思义,Invocation Operation提供了调用普通method来执行task的方法。

3. PlainOperation

继承自NSOperation,自定义NSOperation。在自定义NSOperation时,至少要重写main和/或start函数。也必须重写isExecuting 和isFinished,并通过KVO通知其他对象。你还必须为自定义的Operation指定一个初始化函数。


2.1 NSBlockOperation

先来一个Block Operation同步执行的代码:
- (BOOL) application:(UIApplication *)application  didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
NSBlockOperation *simpleOperation = [NSBlockOperation blockOperationWithBlock:^{ NSUInteger counter = 0;
for (counter = 0; counter < 1000;counter++){
NSLog(@"Count = %lu", (unsigned long)counter);
  } 
}];
[simpleOperation start];
NSLog(@"Main thread is here");
return YES;
}
通过NSLog输出的顺序可以看出,simpleOperation堵塞了mainthread,main thread会等待block执行完成之后再执行。
Operation默认是在创建它的线程中通过start方法来执行,我们可以将simpleOperation加入NSOperationQueue中来实现异步执行,也可以自定义Operation并detach一个新的线程来执行:

NSOperationQueue *queue = [[NSOperationQueueallocinit];   

[queue addOperation:simpleOperation];

当你把一个Operation加入到queue之后,你不用手动的去start,因为queue会帮你完成,queue会管理所有加入到其中的Operation。如果你想自己控制(并不推荐这样做),你可以采用detach thread的方法。
如果有多个Operation需要添加,调用函数:

- (void)addOperations:(NSArray *)ops waitUntilFinished:(BOOL)wait

同时,可以获取queue中当前有哪些Operation以及Operation的数目:

- (NSArray *)operations;

- (NSUInteger)operationCount;

你也可以为queue设置优先级:

- (NSOperationQueuePriority)queuePriority;

- (void)setQueuePriority:(NSOperationQueuePriority)p;

为queue添加一个便于记忆的名字:

- (void)setName:(NSString *)n ;

- (NSString *)name ;

暂停queue:

- (void)setSuspended:(BOOL)b;

- (BOOL)isSuspended;

2.2 NSInvocationOperation

顾名思义,这种Operation就是在一个NSObject对象中去调用方法(method)。同样的,我们先来看一下同步执行的情况:
self.simpleOperation = [[NSInvocationOperation alloc]initWithTarget:self  selector:@selector(simpleOperationEntry:)  object:simpleObject];
[self.simpleOperation start]; 

这样,simpleOperation会在创建它的当前线程中(一般是main thread)执行,并且它的执行会堵塞当前线程。
当然,这样做并没有多大的实际意义,但是如果我们把simpleOperation加入到queue中,它就可以和当前线程并行执行,从而提高效率。
NSNumber *firstNumber = [NSNumber numberWithInteger:111]; 
NSNumber *secondNumber = [NSNumber numberWithInteger:222];
self.firstOperation =[[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(firstOperationEntry:) object:firstNumber];//first
self.secondOperation = [[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(secondOperationEntry:) object:secondNumber];//second
self.operationQueue = [[NSOperationQueue alloc] init];
/* Add the operations to the queue */ 
[self.operationQueue addOperation:self.firstOperation];
[self.operationQueue addOperation:self.secondOperation];
在上面的代码里,两个Operation都在各自的线程中与main thread并行执行,而且这两个Operation之间也是并行的。在queue中可以get、set最大并行Operation数:

- (NSInteger)maxConcurrentOperationCount;

- (void)setMaxConcurrentOperationCount:(NSInteger)cnt;


那么,如果我要让secondOperation在firstOperation之后执行呢?也就是说secondOperation需要等到firstOperation执行完成之后才开始。一个Operation可以依赖于另一个或者多个Operations,即等待依赖于的Operation执行完成之后再执行。如果你没有为一个Operation添加依赖,那么你对它何时执行将没有控制权。
addDependency:方法可以解决这一问题,在添加到queue之前为两个Operation添加依赖属性。

[self.secondOperation addDependency:self.firstOperation]; 

当不再需要依赖的时候,调用removeDependency:取消依赖。
[self.secondOperation removeDependency:self.firstOperation]; 

另外,NSInvocationOperation还可以以指定的初始化函数初始化:

- (id)initWithInvocation:(NSInvocation *)inv;// designated initializer

2.3  Operation其他需要注意的点


一个Operation有相应的状态来标识它的执行过程。

- (BOOL)isCancelled;

- (BOOL)isExecuting;

- (BOOL)isFinished;

- (BOOL)isConcurrent;

- (BOOL)isReady;

通过- (void)cancel可以取消一个Operation。
在queue中,通过- (void)cancelAllOperations来取消所有Operation。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值