iOS平台提供更高级的并发(异步)调用接口,让你可以集中精力去设计需完成的任务代码,避免去写与程序逻辑无关的线程生成、运行等管理代码。当然实质上是这些接口隐含生成线程和管理线程的运行,从而更加简洁地实现多线程。下面先来研究NSOperationNSOperationQueue类的使用。

NSOperation实质是封装了需要并发运行的代码,一些主要接口和NSThread基本相同,可以看做没有线程运行能力的thread类的抽象。参考NSThread,NSOperation的一些相同的接口有:

- (void)start; //在当前任务状态和依赖关系合适的情况下,启动NSOperation的main方法任务,需要注意缺省实现只是在当前线程运行。如果需要并发执行,子类必须重写这个方法,并且使 - (BOOL)isConcurrent 方法返回YES
 - (void)main; //定义NSOperation的主要任务代码
 - (BOOL)isCancelled; //当前任务状态是否已标记为取消
 - (void)cancel; //取消当前NSOperation任务,实质是标记isCancelled状态
 - (BOOL)isExecuting; //NSOperation任务是否在运行
 - (BOOL)isFinished; //NSOperation任务是否已结束
 NSOperation其它常用方法,包括依赖关系:
 - (BOOL)isReady; //是否能准备运行,这个值和任务的依赖关系相关
 - (void)addDependency:(NSOperation //加上任务的依赖,也就是说依赖的任务都完成后,才能执行当前任务
 - (void)removeDependency:(NSOperation //取消任务的依赖,依赖的任务关系不会自动消除,必须调用该方法
 -NSArray //得到所有依赖的NSOperation任务

以及用于任务同步:

- (void)waitUntilFinished; //阻塞当前线程,直到该NSOperation结束。可用于线程执行顺序的同步

- (void)setCompletionBlock:(void (^)(void))block; //设置NSOperation结束后运行的block代码,由于NSOperation有可能被取消,所以这个block运行的代码应该和NSOperation的核心任务无关。

 

除了继承NSOperation来实现并发代码,通常更简便的办法是使用它的两个子类NSInvocationOperationNSBlockOperation,然后加入到NSOperationQueue执行队列中去运行。部分示例代码如下:

NSInvocationOperation *opA = [[NSInvocationOperationalloc] initWithTarget:self selector:@selector(operate)object:nil];
 NSBlockOperation *opB = [NSBlockOperation blockOperationWithBlock:^{
         [self operate];
     }];
 - (void)operate
 {
   //thread loop
   while (condition)
   {
     //....
   }
 }
 NSOperationQueue *queue = [[NSOperationQueuealloc] init];
 queue.maxConcurrentOperationCount = 2; //设置最大并发执行数,如果为1则同时只有一个并发任务在运行,可控制顺序执行关系
 [queue addOperation:opA]; //加入到执行队列中,如果isReady则开始执行
 [queue addOperation:opB]; //同上,需要注意这时opA和opB是在并发运行
 [queue waitUntilAllOperationsAreFinished]; //当前线程等待,直到opA和opB都执行结束
 如果要求opB在opA执行完成后才开始执行,需要加上依赖关系即可:
 [opB addDependency:opA];
 当然也可以使用同步方法waitUntilFinished,在前面的例子中加入:
 NSBlockOperation *opB = [NSBlockOperation blockOperationWithBlock:^{
    [opA waitUntilFinished]; //opB线程等待直到opA执行结束(正常结束或被取消)
 self operate];
     }];
 建立依赖关系或等待关系,一定要出现避免循环依赖或循环等待,否则就会造成线程死锁。
 最后看看NSOperationQueue的其它常用方法:
 - (void)addOperations:(NSArray *)ops waitUntilFinished:(BOOL)wait; //批量加入执行operation,wait标志是否当前线程等待所有operation结束后,才返回
 - (void)addOperationWithBlock:(void (^)(void))block; //相当于加入一个NSBlockOperation执行任务
 - (NSArray //返回已加入执行operation的数组,当某个operation结束后会自动从这个数组清除
 - (NSUInteger)operationCount //返回已加入执行operation的数目
 - (void)setSuspended:(BOOL)b; //是否暂停将要执行的operation,但不会暂停已开始的operation
 - (BOOL)isSuspended; //返回暂停标志
 - (void)cancelAllOperations; //取消所有operation的执行,实质是调用各个operation的cancel方法
 + (id)currentQueue; //返回当前NSOperationQueue,如果当前线程不是在NSOperationQueue上运行则返回nil
 + (id)mainQueue; //返回主线程的NSOperationQueue,缺省总是有一个queue