iOS多线程之NSOperation
在GCD的基础上包装而来,相较于GCD而言,可控性更强,并且加入了操作依赖。
NSOperation是一个抽象的基类,不可直接使用,只能使用其子类,为子类提供了线程的建立状态,优先级,依赖和取消等操作。系统已经给我们封装了NSBlockOperation和NSInvocationOperation这两个实体类,供我们使用,当然我们也可以自定义NSOperation的子类,需要重载-(void)main这个方法。
NSOperation可以自己独立执行(直接调用[operation start]), 也可以放到NSOperationQueue里面执行。NSOperation 在默认情况下是非并发的,当你将此操作放到线程执行,他会阻塞该线程,直到执行完成。NSOperation也可以直接实现并发执行。但需要重写isConcurrent isExecuting isFinished 以及start函数,让isConcurrent 返回YES,再开始结束的时候手动设置 isExecuting isFinished的状态;如果将NSOperation加入NSOperationQueue队列中去执行,那么我们只需去管理NSOperationQueue队列即可,它基本上是并发执行。下面先了解系统提供给我们的NSOperation NSBlockOperation NSInvocationOperation NSOperationQueue的一些属性与方法。
/****************************************NSOperation方法属性************************************************/
NSOperation方法属性
- (void)start;//开始执行操作
- (void)main;//操作入口函数
@property (readonly, getter=isCancelled) BOOL cancelled;//操作状态,表示操作是否取消
- (void)cancel;//取消操作,将cancelled状态置成YES,而非取消操作
@property (readonly, getter=isExecuting) BOOL executing;//操作状态,表示操作是否正在执行
@property (readonly, getter=isFinished) BOOL finished;//操作状态,表示操作是否结束
@property (readonly, getter=isConcurrent) BOOL concurrent; // 判断操作是否并行
@property (readonly, getter=isAsynchronous) BOOL asynchronous ;// 判断操作是否异步
@property (readonly, getter=isReady) BOOL ready;// 判断操作准备完成
- (void)addDependency:(NSOperation *)op;//添加依赖操作
- (void)removeDependency:(NSOperation *)op;//移除依赖操作
@property (readonly, copy) NSArray<NSOperation *> *dependencies;//操作依赖组
typedef NS_ENUM(NSInteger, NSOperationQueuePriority) {//操作队列优先级
NSOperationQueuePriorityVeryLow = -8L,//低
NSOperationQueuePriorityLow = -4L,//较低
NSOperationQueuePriorityNormal = 0,//正常
NSOperationQueuePriorityHigh = 4,//较高
NSOperationQueuePriorityVeryHigh = 8//高
};
@property NSOperationQueuePriority queuePriority;//操作队列优先级
@property (nullable, copy) void (^completionBlock)(void) ;//操作完成后执行函数
- (void)waitUntilFinished ;//操作对象等待知道某个任务结束
@property double threadPriority ;//线程优先级
@property NSQualityOfService qualityOfService ;//操作对象优先级
@property (nullable, copy) NSString *name ;//操作对象名称
/*****************************************NSBlockOperation方法属性*********************************************/
+ (instancetype)blockOperationWithBlock:(void (^)(void))block;//初始化操作对象
- (void)addExecutionBlock:(void (^)(void))block;//添加操作任务
@property (readonly, copy) NSArray<void (^)(void)> *executionBlocks;//执行的任务集数组
/***************************************NSInvocationOperation方法属性 *****************************************/
- (nullable instancetype)initWithTarget:(id)target selector:(SEL)sel object:(nullable id)arg;//初始化操作对象,封装要执行的任务
- (instancetype)initWithInvocation:(NSInvocation *)inv ;初始化操作对象,封装要执行的任务
@property (readonly, retain) NSInvocation *invocation;//要执行的任务
@property (nullable, readonly, retain) id result;//操作结果
static const NSInteger NSOperationQueueDefaultMaxConcurrentOperationCount = -1;//操作队列默认最大并行操作数
/*************************************** NSOperationQueue 方法属性 *****************************************/
- (void)addOperation:(NSOperation *)op;//给操作队列添加操作
- (void)addOperations:(NSArray<NSOperation *> *)ops waitUntilFinished:(BOOL)wait ;//给操作队列添加操作
- (void)addOperationWithBlock:(void (^)(void))block;//给操作队列以块的形式添加操作
@property (readonly, copy) NSArray<__kindof NSOperation *> *operations;//操作队列操作集(所有操作)
@property (readonly) NSUInteger operationCount;//操作队列操作个数(所有操作总数目)
@property NSInteger maxConcurrentOperationCount;//操作队列并发执行操作个数最大个数,如果设为1,那么就成了串行操作了。
@property (getter=isSuspended) BOOL suspended;//操作队列是否挂起
@property (nullable, copy) NSString *name;//操作队列名称
@property NSQualityOfService qualityOfService;//操作队列优先级
@property (nullable, assign /* actually retain */) dispatch_queue_t underlyingQueue;//潜在的队列
- (void)cancelAllOperations;//取消操作队列中的所有操作
- (void)waitUntilAllOperationsAreFinished;//等待直到所有操作完成
{
NSInvocationOperation *myInvocationOpt=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(myFunc:) object:@"invocation"];
[myInvocationOpt setName:@"InvocationOperation"];
[myInvocationOpt start];
/*NSBlockOperation操作示例,添加的操作大于1时,开启新线程进行异步操作*/
NSBlockOperation *myBlockOpt = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"task:%@",[NSThread currentThread]);
}];
[myInvocationOpt setName:@"BlockOperation"];
[myOpt addExecutionBlock:^{
NSLog(@"block:%@",[NSThread currentThread].name);
}];
[myOpt addExecutionBlock:^{
NSLog(@"task-block:%@",[NSThread currentThread]);
}];
[myBlockOpt start];
/*自定义myOperation操作示例,添加的操作大于1时,开启新线程进行异步操作*/
myOperation *myOpt=[[myOperation alloc]init];//自定义NSOperation子类,重写main函数,当调用start函数后,自动开始从入口函数main执行操作
[myOpt setName:@"myOperation"];
[myOpt start];
/*用于操作队列并发执行时的顺序执行,myOpt在myBlockOpt执行完成后开始执行,而myInvocationOpt在myOpt执行完成后开始执行
[myOpt addDependency:myBlockOpt];
[myInvocationOpt addDependency:myOpt];*/
/*其他属性或函数可以自行尝试,根据功能需要自行添加*/
}-(void)myFunc:(NSString *)str
{
NSLog(@"task-invocation:%@----------%@",[NSThread currentThread],str);
}
NSOperationQueue队列多线程示例-(void)operationQueue
{
/*队列的初始化,并设置并发数目*/
NSOperationQueue *myOptQueue=[[NSOperationQueue alloc]init];
[myOptQueue setName:@"hello"];
[myOptQueue setMaxConcurrentOperationCount:3];
/*NSBlockOperation操作对象的初始化 */
NSBlockOperation *myBlock=[NSBlockOperation blockOperationWithBlock:^{
NSLog(@"My First Task");
}];
/*NSBlockOperation操作对象以块的形式添加任务*/
[myBlock addExecutionBlock:^{
NSLog(@"My Sencond Task");
}];
[myBlock addExecutionBlock:^{
NSLog(@"My Third Task");
}];
/*NSInvocationOperation操作对象初始化*/
NSInvocationOperation *myInvocation=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(myFunc:) :@"NSInvocationOperation"];
[myInvocation setQueuePriority:NSOperationQueuePriorityVeryLow];//设置优先级
[myBlock addDependency:myInvocation];//添加依赖,myBlock执行与myInvocation之后
[myOptQueue addOperation:myInvocation];//给操作队列添加myInvocation操作
//[myInvocation cancel];设置myInvocation操作状态cancelled为YES,如果该操作还未执行,就取消该操作,不再执行;在执行中,等待执行完成,设置标志完成
[myOptQueue addOperation:myBlock]; //给操作队列添加myBlock操作
[myOptQueue addOperationWithBlock:^{ //给操作队列添加块操作
NSLog(@"My Fourth Task");
}];
//[myOptQueue cancelAllOperations];//取消操作队列中所有的操作
[myOptQueue setSuspended:YES];//挂起本操作队列
if([myOptQueue isSuspended])
{
NSLog(@"setSuspended:YES");
[myOptQueue setSuspended:NO];//恢复本操作队列
}
myInvocation.completionBlock=^{ //myInvocation操作结束后调用
NSLog(@"myInvocation over!!!");
};
}