IOS任务管理之NSOperation使用
前言:
前面学习了NSThread使用,今天学习一下apple提供的多线程解决方案NSOperation,NSOperation是基于GCD开发,相对于GCD来说可控性更强,并且可以加入操作依赖。
NSOperation
NSOperation
表示了一个独立的计算单元。作为一个抽象类,它给了它的子类一个十分有用而且线程安全的方式来建立状态、优先级、依赖性和取消等的模型。系统已经给我们封装了NSInvocationOperation和NSBlockOperation这两个实体类, 接下来看下这两个子类的使用,同样我们也可以通过自定义NSOperation。
NSInvocationOperation
//创建NSInvocationOperation操作对象,封装要执行的任务 NSInvocationOperation *operation= [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(operationTask) object:nil]; //设置任务优先级 [operation setQualityOfService:NSQualityOfServiceUserInteractive]; //设置任务优先级 [operation setQueuePriority:NSOperationQueuePriorityHigh]; //设置任务名称 [operation setName:@"operation-1"]; //启动执行任务 [operation start]; //取消执行任务 [operation cancel];
然后我们来看下operationTask函数
-(void)operationTask { [NSThread sleepForTimeInterval:2]; NSLog(@"operationTask:%@ isMainThread:%@",[NSThread currentThread],[[NSThread currentThread] isMainThread]?@"YES":@"NO"); }
运行结果:
通过运行结果会发现,竟然执行在主线程中,所以使用这种方式是同步方式而非异步方式。
NSBlockOperation
//创建NSBlockOperation操作对象 NSBlockOperation *operation=[NSBlockOperation blockOperationWithBlock:^{ NSLog(@"operationTask:%@ isMainThread:%@",[NSThread currentThread],[[NSThread currentThread] isMainThread]?@"YES":@"NO"); }]; //添加操作 [operation addExecutionBlock:^{ NSLog(@"operationTask:%@ isMainThread:%@",[NSThread currentThread],[[NSThread currentThread] isMainThread]?@"YES":@"NO"); }]; //设置任务优先级 [operation setQualityOfService:NSQualityOfServiceUserInteractive]; //设置任务优先级 [operation setQueuePriority:NSOperationQueuePriorityHigh]; //设置任务名称 [operation setName:@"operation-1"]; //启动执行任务 [operation start]; //取消执行任务 [operation cancel];
运行结果
通过运行结果会发现,第一个block运行在主线程中,第二block运行在子线程中,因此,NSBlockOperation只有在封装的操作数大于1时才会开启子线程执行,否则默认执行在主线程。
自定义NSOperation
有时上述的连个子类不能满足我们的需求,需要我们自定义NSOperation,我们只需修改mian函数即可。
XLTaskOperation.h
#import <Foundation/Foundation.h> @interface XLTaskOperation : NSOperation @property (nonatomic, copy) NSString *key; @property (nonatomic, copy) void(^sucessBlock)(NSString *) ; @end
XLTaskOperation.m
#import "XLTaskOperation.h" @implementation XLTaskOperation -(void)main { NSLog(@"operationTask:%@ isMainThread:%@",[NSThread currentThread],[[NSThread currentThread] isMainThread]?@"YES":@"NO"); NSMutableString *mutableString=[[NSMutableString alloc]initWithString:self.key]; [mutableString appendString:@" from cache"]; //回到主线程,通过block传递数据 dispatch_async(dispatch_get_main_queue(), ^{ if(self.sucessBlock){ self.sucessBlock(mutableString); } }); } @end
使用方式
XLTaskOperation *xlTaskOperation =[[XLTaskOperation alloc]init]; xlTaskOperation.key=@"whoislcj"; xlTaskOperation.sucessBlock=^(NSString * cache){ NSLog(@"operationTask:%@ cache: %@",[NSThread currentThread],cache); }; [xlTaskOperation start];
运行结果
同样也是默认运行在主线程中。
NSOperationQueue
通过上面的三种方式生成NSOperation调用start函数,因为都是默认执行在主任务队列mainQueue中,所以才会执行在主线程中,如果采用下面这种方式都会执行在异步子线程中。
//创建NSOperationQueue NSOperationQueue * queue=[[NSOperationQueue alloc]init]; //设置NSOperationQueue最大并发任务数 queue.maxConcurrentOperationCount=3; NSInvocationOperation *operation1= [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(operationTask) object:nil]; NSInvocationOperation *operation2= [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(operationTask) object:nil]; NSBlockOperation *operation3=[NSBlockOperation blockOperationWithBlock:^{ [NSThread sleepForTimeInterval:1]; NSLog(@"operationTask:%@ isMainThread:%@",[NSThread currentThread],[[NSThread currentThread] isMainThread]?@"YES":@"NO"); }]; [operation3 addExecutionBlock:^{ [NSThread sleepForTimeInterval:1]; NSLog(@"operationTask:%@ isMainThread:%@",[NSThread currentThread],[[NSThread currentThread] isMainThread]?@"YES":@"NO"); }]; [queue addOperation:operation1]; [queue addOperation:operation2]; [queue addOperation:operation3]; for (int i =0; i<9; i++) { [queue addOperationWithBlock:^{ [NSThread sleepForTimeInterval:1]; NSLog(@"operationTask:%@ isMainThread:%@",[NSThread currentThread],[[NSThread currentThread] isMainThread]?@"YES":@"NO"); }]; }
operationTask函数同上,看下运行结果
因为上面设置了最大并行线程数为3,但是我实测却创建了4个线程,这点我有点不太理解,每次并行执行3个。
总结:
简单学习了NSOperation的使用。
干我们这行,啥时候懈怠,就意味着长进的停止,长进的停止就意味着被淘汰,只能往前冲,直到凤凰涅槃的一天!