NSOperation 是苹果公司对 GCD 的封装,了解GCD的朋友们使用起来并不会陌生,大家可以看到 NSOperation和NSOperationQueue分别对应 GCD 的任务和队列。操作步骤也很好理解:先将需要执行的操作封装到一个NSOperation对象中,然后将NSOperation对象添加到NSOperationQueue中。
系统会自动将NSOperationQueue中的NSOperation取出来,放到一条新线程中执行。但NSOperation 是个抽象类,本身并不具备封装的能力,所以我们需要使用它的子类。一般是以下三种使用方式:
1.NSInvocationOperation
2.NSBlockOperation
3.自定义子类继承NSOperation
NSInvocationOperation使用只需两步:
1.创建NSInvocationOperation对象
-(id)initWithTarget:(id)target selector:(SEL)selobject:(id)arg;
2.调用start方法开始执行操作
-(void)start;
不过有两个注意点:
1.默认情况下调用start方法后并不会开启新线程,会在当前线程同步执行
2.只有将NSOperation放到一个NSOperationQueue中,才会异步执行操作
NSBlockOperation的使用更为方便:
1.创建NSBlockOperation对象
+ (id)blockOperationWithBlock:(void(^)(void))block;
2.根据需要通过addExecutionBlock:方法添加更多的操作
-(void)addExecutionBlock:(void(^)(void))block;
注意点:只要NSBlockOperation的操作数大于1,Operation 中的任务 会并发执行,它会在主线程 和 其它的多个线程执行这些任务
自定义继承NSOperation:
1.继承 NSOperation 类,并实现其 main 方法,因为在调用 start 方法的时候,内部会调用 main 方法完成相关逻辑
2.当苹果提供的两个类无法满足我们的需求时,我们就需要用到自定义,而且自定义也更有利于封装和重用
注意点:需要自动创建释放池,通过- (BOOL)isCancelled方法检测操作是否被取消,对取消做出响应
有些朋友这时候就会发现,NSOperation和GCD比较时,少了一个串行队列,那么如果我们需要串行执行多个任务,应该怎么操作呢?苹果在这里引入了一个方法— — “最大并发数 - (NSInteger)maxConcurrentOperationCount;”,可以用来控制最多多少个任务同时执行,如果把它设置为1,其实就是串行啦!
NSOperation还有一个非常实用的功能那就是操作依赖。NSOperation之间任务可以设置依赖来保证按顺序执行,也可以在不同的队列之间依赖,反正就是这个依赖是添加到任务身上的,和队列没关系。
比如一定要让操作A执行完后,才能执行操作B:
[operationB addDependency : operationA];// 操作B依赖于操作A
注意:不能添加相互依赖,会造成死锁,比如 A依赖B,B依赖A。
最后补充一下就是关于队列的取消、暂停和恢复,我个人觉得NSOperation中这几个操作要比GCD更加方便
-(void)cancelAllOperations; 取消所有队列操作
-(void)setSuspended:(BOOL)b;// YES代表暂停队列,NO代表恢复队列
-(BOOL)isSuspended;
关于多线程的介绍就到此结束啦,如果大家有更多更好的想法欢迎一起分享。