认识和使用NSOperation
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的更多相关文章
- iOS多线程之9.自定义NSOperation
本文主要讲如何自定义NSOperation,以及自定义NSOperation的一些注意事项,以下载图片为例. 新建一个类,继承于NSOperation. CustomOperation.h 代码 ...
- iOS多线程之8.NSOPeration的其他用法
本文主要对NSOPeration的一些重点属性和方法做出介绍,以便大家可以更好的使用NSOPeration. 1.添加依赖 - (void)addDependency:(NSOperation * ...
- iOS多线程之7.NSOperation的初识
NSOperation和GCD一样,不用我们管理线程的生命周期,加锁等问题,只要把操作封装进NSOperation中,系统会自动帮我们创建线程,执行操作.而且他是面向对象的,我们看起来更容易理解,使用 ...
- 4.4 多线程进阶篇<下>(NSOperation)
本文并非最终版本,如有更新或更正会第一时间置顶,联系方式详见文末 如果觉得本文内容过长,请前往本人"简书" 本文源码 Demo 详见 Github https://github.c ...
- 多线程下NSOperation、NSBlockOperation、NSInvocationOperation、NSOperationQueue的使用
本篇文章主要介绍下多线程下NSOperation.NSBlockOperation.NSInvocationOperation.NSOperationQueue的使用,列举几个简单的例子. 默认情况下 ...
- iOS NSOperation 封装 通知实现界面更新
#import <Foundation/Foundation.h> #import <UIKit/UIKit.h> @interface MYOperation : NSOpe ...
- iOS NSOperation 异步加载图片 封装NSOperation 代理更新
#import <Foundation/Foundation.h> @class MYOperation; @protocol MYOperationDelecate <NSObje ...
- 3.多线程NSOperation
1.NSOperation的基本操作 使用NSOperation的两个子类,NSInvocationOperation 和 NSBlockOperation 创建操作,然后将操作添加到队列中去执行 / ...
- NSOperation的start与main,并发与非并发。
http://blog.csdn.net/a2331046/article/details/52294006 在ios4以前,只有非并发的情况下,队列会为operation开启一个线程来执行.如果是并 ...
随机推荐
- 谈谈yii2-GridView如何实现列表页直接修改数据
作者:白狼 出处:http://www.manks.top/yii2_gridview_advanced.html 本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原 ...
- 47个过程(PMBOK2008)
项目管理过程 知识领域 过程组 含义 之前应完成 之后要进行 制定项目章程 整合 启动 编写一份正式批准项目并授权项目经理使用组织资源的文件的过程 无 制定项目管理计划 制定项目管理计划 整合 规划 ...
- IIS7如何部署asp.net网站
第一步:发布网站 右键asp.net web项目,选择发布, 然后新建配置文件名称并选择 "文件系统" 发布方法. 目标位置选择本地新建的文件夹如: IISWebSite 第二 ...
- DBCC CheckDB遇到a database snapshot could not be created
在备份一个客户的数据库时(数据库版本为SQL 2005 Express版本),做DBCC CHECKDB时遇到了下面错误信息: dbcc checkdb('DB_NAME'); 消息 5030,级别 ...
- MS SQL巡检系列——检查数据库上一次DBCC CHECKDB的时间
DBCC CHECKDB检查指定数据库中的所有对象的逻辑和物理完整性,具体请参考MSDN文档.我们必须定期对数据库做完整性检查(DBCC CHECKDB),以便能及时发现一些数据库损坏(Corrupt ...
- SQL Server 2008 安装过程中遇到“性能计数器注册表配置单元一致性”检查失败 问题的解决方法
操作步骤: 1. 在 Microsoft Windows 2003 或 Windows XP 桌面上,依次单击"开始"."运行",然后在"打开&quo ...
- DbVisualizer连接hbase
1.添加phoneix驱动 (1).点击Tools--->Driver Manager- (2).新建一个驱动,名称为phoenix(名称随意),选择phoenix的客户端驱动,驱动类如图所示 ...
- 使用js 设置组合快捷键
使用js 设置组合快捷键 使用js设置快捷键的本质就是获得你要设置的这个键的keyCode 的值,如果要加ctrl,alt,shift,那么就添加一个ctrlkey,altKey,shiftKey来判 ...
- linux命令:ls
命令格式: ls [OPTION]... [FILE]... 功能: 列出某个目录下的文件信息,默认列出当前目录.输出结果默认按字母顺序排列. 参数: -a, --all,-A, --almost-a ...
- Linux下TomcatVM参数修改:Native memory allocation (mmap) failed to map 3221225472 bytes for committing reserved memory.
不可行的方法最初我直接修改catalina.sh, 将JAVA_OPTS变量加上了 -server -Xms1G -Xmx1G -XX:+UserG1GC最初看起来没啥问题,但是当服务器运行几天后,发 ...