认识和使用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开启一个线程来执行.如果是并 ...
随机推荐
- C#结合Jquery LigerUI Tree插件构造树
Jquery LigerUI Tree是Jquery LigerUI()的插件之一,使用它可以快速的构建树形菜单.呵呵 废话不说了,直入正题,下面介绍C#结合ligerui 构造树形菜单的两种方法 1 ...
- SQLite学习笔记(九)&&pager模块
概述 通过上一篇文章的分析,我们知道了pager模块在整个sqlite中所处的位置.它是sqlite的核心模块,充当了多种重要角色.作为一个事务管理器,它通过并发控制和故障恢复实现事务的ACID特性, ...
- InstallShield如何做Excel安装与否的检测
传统的方法 一般都会从注册表入手,检测注册表中是否存在某项来判断是否安装了Office,还可以通过注册表信息来判断安装的具体版本. 存在的问题 由于系统的不同.注册表的损坏.安装包的不同等等原因,读取 ...
- XmlSerializer的使用
关键词: XmlSerializer StreamWriter T instance 保存xml文件 代码: public static void SaveXML<T>(string xm ...
- (转)Div和Table的区别
原文:http://www.cnblogs.com/lovebear/archive/2012/04/18/2456081.html Div与table的区别 1:速度和加载方式方面的区别 div 和 ...
- C#按位操作,直接操作INT数据类型的某一位
/// <summary> /// 根据Int类型的值,返回用1或0(对应True或Flase)填充的数组 /// <remarks>从右侧开始向左索引(0~31)</r ...
- RSA加密算法的简单案例
RSA加密算法是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击. 那关于RSA加密算法有哪些应用呢?以下举一个数据库身份验证的案例. 在使用数据集进行身份认证时,密码存在数据 ...
- maven私服搭建
一.软件安装 地址:http://www.sonatype.org/nexus/thank-you-for-downloading/?dl=tgz 解压: 启动: >> nexus sta ...
- Counting Bits -leetcode
introduction: Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num ...
- oracle异常(-)
一.概述异常分成三大类:预定义异常.非预定义异常.自定义异常处理方法分为:直接抛出异常.内部块处理异常.游标处理异常 预定义异常:由PL/SQL定义的异常.由于它们已在standard包中预定义了,因 ...