前言:
前面学习了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的使用。