NSOperation基本使用
NSOperation简单介绍
a. 是OC语言中基于GCD的面向对象的封装 b. 使用起来比GCD更加简单(面向对象) c. 提供了一些用GCD不好实现的功能 d. 苹果推荐使用,使用NSOperation不用关心线程以及线程的生命周期 1. NSOperation是一个抽象类 i. 不能直接使用(方法没有实现) ii. 约束子类都具有共同的属性和方法 2. NSOperation的子类 i. NSInvocationOperation ii. NSBlockOperation 3.NSOperationQueue 队列
NSInvocationOperation代码演示
1. 执行操作 //创建操作 NSInvocationOperation* op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadFile:) object:@"fileName"]; //在当前线程执行方法(开始执行操作) [op start]; 2. 把操作添加到队列(并开始异步执行) //创建操作 NSInvocationOperation* op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadFile:) object:@"fileName"]; //将操作添加到队列,会自动异步调用方法 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [queue addOperation:op]; - (void)downloadFile:(id)object { NSLog(@"下载:%@----线程:%@", object, [NSThread currentThread]); } 3. 开启多个线程, 不会顺序执行-- -》GCD并发队列, 异步执行 //队列 NSOperationQueue* queue = [[NSOperationQueue alloc] init]; for (int i = 0; i < 10; i++) { //创建操作 NSInvocationOperation* op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadFile:) object:@(i)]; //将操作添加到队列,会自动异步调用方法 [queue addOperation:op]; } - (void)downloadFile:(id)object { NSLog(@"下载:%@----线程:%@", object, [NSThread currentThread]);
NSBlockOperation代码演示
//1. NSBlockOperation //队列 NSOperationQueue* queue = [[NSOperationQueue alloc] init]; for (int i = 0; i < 10; i++) { //操作 NSBlockOperation* op = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"down %d %@", i, [NSThread currentThread]); }]; [queue addOperation:op]; } //2. NSOperationQueue添加block的operation代码更简练 NSOperationQueue* queue = [[NSOperationQueue alloc] init]; for (int i = 0; i < 10; i++) { [queue addOperationWithBlock:^{ NSLog(@"down %d %@", i, [NSThread currentThread]); }]; } //3. 全局操作队列(controller的全局), 调度所有的异步操作 定义属性 @property (nonatomic, strong) NSOperationQueue* queue; //懒加载队列 - (NSOperationQueue*)queue { if (_queue == nil) { _queue = [[NSOperationQueue alloc] init]; } return _queue; } for (int i = 0; i < 10; i++) { [self.queue addOperationWithBlock:^{ NSLog(@"down %d %@", i, [NSThread currentThread]); }]; } //4. 监听操作完成 [op1 setCompletionBlock:^{ NSLog(@"....."); }];
线程间通讯
//1. 主队列 添加到主队列的操作,最终都执行在主线程上 [NSOperationQueue mainQueue] //获取当前操作所在的队列 [NSOperationQueue currentQueue] [self.queue addOperationWithBlock:^{ NSLog(@"异步执行的 %@", [NSThread currentThread]); //获取主队列 [[NSOperationQueue mainQueue] addOperationWithBlock:^{ NSLog(@"主线程?%@", [NSThread currentThread]); //当前队列是谁呢? 正在执行操作的队列 [[NSOperationQueue currentQueue] addOperationWithBlock:^{ NSLog(@"当前队列是谁呢 %@", [NSThread currentThread]); }]; }]; }];
NSOperation中的方便的使用
1. 最大并发数
self.queue.maxConcurrentOperationCount = 2; for (int i = 0; i < 20; i++) { [self.queue addOperationWithBlock:^{ //加上此代码后执行的过程? [NSThread sleepForTimeInterval:1]; NSLog(@"%@---%d", [NSThread currentThread], i); }]; } • 执行过程 1、把操作添加到队列 self.queue addOperationWithBlock 2、去线程池去取空闲的线程, 如果没有就创建线程 3、把操作交给从线程池中取出的线程执行 4、执行完成后, 把线程再放回线程池中 5、重复2, 3, 4知道所有的操作都执行完
2. 队列的暂定/继续 取消
1. 暂停 判断队列是否是挂起状态时, 并不会判断队列中是否有操作 我们可以先判断下队列是否为空 if (self.queue.operationCount == 0) { NSLog(@"队列中没有操作"); return; } 2. 继续 - (IBAction)pause { if (self.queue.operationCount == 0) { NSLog(@"队列中没有操作"); return; } if (self.queue.isSuspended) { //继续 self.queue.suspended = NO; NSLog(@"继续"); } else { //挂起(暂定) self.queue.suspended = YES; NSLog(@"暂停"); } //当前队列的操作数 NSLog(@"%lu", self.queue.operationCount); } 3. 取消(清除队列中的操作) - (IBAction)cancel { [self.queue cancelAllOperations]; NSLog(@"取消"); NSLog(@"%lu", self.queue.operationCount); } 4. 等待队列中的操作执行完毕 //等待队列中的操作执行完毕,会阻塞 [self.queue waitUntilAllOperationsAreFinished]; NSLog(@"over");
依赖关系
1. 模拟软件的部分升级 //依赖关系 //模拟软件的部分升级 //下载压缩包 NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"下载 %@",[NSThread currentThread]); }]; //解压,复制到相应目录 NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"解压 %@",[NSThread currentThread]); }]; //通知用户 NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"通知用户升级完成 %@",[NSThread currentThread]); }]; //设置操作的依赖关系 [op2 addDependency:op1]; [op3 addDependency:op2]; //添加操作 //waitUntilFinished YES 等待所有的操作执行完成 会阻塞窗体的执行 //waitUntilFinished NO 不等待 [self.queue addOperations:@[op1,op2,op3] waitUntilFinished:NO]; NSLog(@"over"); 2. 循环依赖 发生循环依赖,程序不会死锁。界面也不会阻塞,操作不会执行 [op2 addDependency:op1]; [op3 addDependency:op2]; [op1 addDependency:op3]; 3. 依赖关系可以快队列执行 //设置操作的依赖关系 [op2 addDependency:op1]; [op3 addDependency:op2]; [self.queue addOperations:@[op1,op2] waitUntilFinished:NO]; NSLog(@"over"); [[NSOperationQueue mainQueue] addOperation:op3];