认识和使用NSOperation
来源:互联网 发布:async await python 编辑:程序博客网 时间:2024/04/29 21:44
转自:http://www.jianshu.com/p/813f7d58935d
NSOperation是OC中多线程技术的一种,是对GCD的OC包装.它包含队列(NSOperationQueue)
和操作(NSOperation)
两个基本要素.
通过这篇文章你可以了解到:
- 怎样使用NSOperation
- 怎样使用NSOperationQueue
- 如何给NSOperationQueue设置并发数
- NSOperationQueue的暂停恢复和取消
- 通过添加依赖影响操作的执行顺序
- NSOperation的进程间通信
怎样使用NSOperation
- NSOperation本身是一个抽象类,要使用可以通过以下几个办法:
- 使用NSInvocationOperation
- 使用NSBlockOperation
- 自定义NSOperation的子类
使用
- NSInvocationOperation
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task) object:nil];// 调用start方法执行操作op操作[op start];
- NSBlockOperation
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"task0---%@", [NSThread currentThread]);}];[op start];
根据打印的结果我们会发现,直接调用start
方法时,系统并不会开辟一个新的线程去执行任务,任务会在当前线程同步执行.
注意: 这里我们说的是当前线程
而非主线程,意即:如果是在主线程中调用op的start方法,那么该任务是在主线程中执行;但如果是在其他子线程调用start方法,任务则是在其他子线程执行.
当然NSBlockOperation还有一种使用方法addExecutionBlock:
使得我们可以给其添加更多的操作,使用如下:
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"task0---%@", [NSThread currentThread]);}];[op addExecutionBlock:^{ NSLog(@"task1----%@", [NSThread currentThread]);}];[op addExecutionBlock:^{ NSLog(@"task2----%@", [NSThread currentThread]);}];// 开始必须在添加其他操作之后[op start];
由打印的结果发现: task0的结果和前面的结论一样,是执行在主线程中的(因为是在主线程中调用start方法),但task1和task2都是在自己的新线程中执行.也就是说:当NSBlockOperation封装的操作数大于1的时候,就会执行异步操作.
- 自定义NSOperation
自定义NSOperation的方法也很简单,我们需要做到下面几个步骤:
1.子类化NSOperation
2.在.m文件里面实现-(void)main方法
3.初始化该操作的时候直接调用alloc及init即可
4.同样可以通过start方法让你自定义的任务跑在当前线程中
关键代码:
自定义NSOperation的实现文件:
#import "AROperation.h"@implementation AROperation- (void)main { NSLog(@"this is my custom operation ---- %@", [NSThread currentThread]);}@end
使用(在任何需要启用该任务的地方):
// 该操作被执行时就会执行op内部定义的任务AROperation *op = [[AROperation alloc] init];[op start];
怎样使用NSOperationQueue
NSOperation的start方法默认是同步执行任务,这样的使用并不多见,只有将NSOperation与NSOperationQueue进行结合,才会发挥出这种多线程技术的最大功效.当NSOperation被添加到NSOperationQueue中后,就会全自动地执行异步操作.
NSOperationQueue的种类:
- 自带主队列
[NSOperationQueue mainQueue]
: 添加到主队列中的任务都会在主线程中执行 - 自己创建队列(非主队列)
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
: 这种队列同时包含串行、并发的功能,添加到非主队列的任务会自动放到子线程中执行
- 自带主队列
向NSOperationQueue中添加操作:
- 直接添加
[queue addOperation:op1];
- 使用block添加,block的内容会被包装成operation对象添加到队列
[queue addOperationWithBlock:^{}];
操作一但被到添加到队列中,就会自动异步执行.
- 直接添加
设置NSOperationQueue的最大并发数
NSOperationQueue可以通过以下方法设置最大并发数,setMaxConcurrentOperationCount:
,值得注意的是:当并发数为1就变成了串行执行任务
NSOperationQueue的暂停恢复和取消
- 取消
- NSOperation有一个
cancel
方法可以取消单个操作 - NSOperationQueue的
cancelAllOperations
相当于队列中的每个operation调用了cancel方法,会取消队列里面全部的操作. - 但是,不能取消正在进行中的任务,队列调用了cancelAllOperations后会等当前正在进行的任务执行完闭后取消后面的操作
- NSOperation有一个
- 挂起和恢复
isSuspended
: 判断是否挂起setSuspended
: YES表示挂起,NO表示恢复- 和取消功能类似,我们同样不能挂起正在运行中的操作,队列会等当前操作结束后将后面的操作暂停(挂起)
因此, 我们在自定义NSOperation的时候需要注意,最好可以经常通过判断isCancelled方法检测操作是否被取消,以响应外部可能进行的取消操作.如:
// 自定义NSOperation类.m文件的main方法实现- (void)main { for (NSInteger i = 0; i < 1000; i++) { NSLog(@"SubTask---0---%zd",i); } // 判断当前任务是否被取消,如果已经取消,及时返回 if (self.cancelled) { return; } for (NSInteger i = 0; i < 1000; i++) { NSLog(@"SubTask---1---%zd", i); } if (self.cancelled) { return; } for (NSInteger i = 0; i < 1000; i++) { NSLog(@"SubTask---2---%zd",i); }}
添加依赖和监听
- 通过设置操作间的依赖,可以确定这些操作的执行顺序
如:
[op3 addDependency:op1];[op3 addDependency:op2];表示op3会在op1和op2都执行完毕后才执行
添加依赖的时候要注意防止添加循环依赖,此外我们还可以在不同队列的operation之间添加依赖
- 监听
op.completeBlock
可以监听一个操作执行完毕的时刻,这个block里面可以添加一些我们需要执行的操作- 这个block里面的操作仍然是在子线程执行,但不一定和被监听的操作在同一个线程
线程间通信
有时我们在子线程中执行完一些操作的时候,需要回到主线程做一些事情(如进行UI操作),因此需要从当前线程回到主线程,以下载并显示图片为例,方法如下:
NSOperationQueue *queue = [[NSOperationQueue alloc] init];// 子线程下载图片[queue addOperationWithBlock:^{ NSURL *url = [NSURL URLWithString:@"http://img.pconline.com.cn/images/photoblog/9/9/8/1/9981681/200910/11/1255259355826.jpg"]; NSData *data = [NSData dataWithContentsOfURL:url]; UIImage *image = [[UIImage alloc] initWithData:data]; // 回到主线程进行显示 [[NSOperationQueue mainQueue] addOperationWithBlock:^{ self.imageView.image = image; }];}];
NSOperation的使用还是比较简单的,但是要注意的细节比较多,一些方法比较容易被忽略,于是乎特此总结一下.这里就不上传示例代码了,有问题的童鞋可以直接留言.
- 认识和使用NSOperation
- 认识和使用NSOperation
- NSOperation和NSOperationQueue的使用
- NSOperation的介绍和使用
- 使用NSOperation和NSOperationQueue启动多线程
- 使用NSOperation和NSOperationQueue启动多线程
- 使用NSOperation和NSOperationQueue启动多线程
- 使用NSOperation和NSOperationQueue启动多线程
- 使用NSOperation和NSOperationQueue启动多线程
- 使用NSOperation和NSOperationQueue启动多线程
- 使用NSOperation和NSOperationQueue用来实现多线程
- 多线程的使用(2) - NSOperation和NSOperationQueue
- iOS多线程 NSOperation和NSOperationQueue的使用
- 多线程的使用(2) - NSOperation和NSOperationQueue
- NSoperation和GCD的使用场景
- NSOperation及其子类简单介绍和使用
- 多线程的使用(2) - NSOperation和NSOperationQueue
- 多线程NSOperation--NSInvocationOperation 和 NSBlockOperation 使用(一)
- [BZOJ4260][字典树]Codechef REBXOR
- 个人--对重写equals与hashcode理解
- Jquery datatable中文排序问题
- QRCode插件生成二维码
- 将GrADS数据转化为netCDF文件
- 认识和使用NSOperation
- Qt namespace Ui
- Nginx/LVS/HAProxy负载均衡软件的优缺点详解
- 移动端 rem 适配
- html与css布局(含flex)
- 【进程通信】之消息队列
- loadrunner之手动关联
- Gradle多项目构建并将项目导入到Eclipse
- windows server2008 创建新用户 远程桌面连接 和 多用户登录问题