iOS多线程--NSOperation
NSOperation是基于GCD的一套多线程实现方案,和GCD一样,线程的生命周期是由系统来自动管理的,不用像NSThread和Pthread一样让程序员手动管理。相对于GCD来说,它更加地面向对象,并且比GCD多了一些更加简单实用的功能,另外,由于它的API是纯OC的,深受广大程序员喜爱,实用频率很高。
NSOperation主要和NSOperationQueue配合使用实现多线程,一般步骤如下:
1.先将需要执行的操作封装到一个NSOperation对象中;
2.然后将NSOperation对象添加到NSOperationQueue中;
3.系统会自动将NSOperationQueue中的NSOperation取出来;
4.将取出的NSOperation放到一条线程中执行。
注意:NSOperation是一个抽象类,并不具备封装操作的能力,必须使用它的子类。使用NSOperation子类的方式有如下三种:
1.NSInvocationOperation
2.NSBlockOperation
3.自定义子类继承NSOperation,实现内部相应的方法。
我们首先来看前两种:
一、NSOperation:
- (void)viewDidLoad {
[super viewDidLoad];
[self invocationOperation];
}
-(void)invocationOperation
{
// 1.创建操作对象,封住需要执行的任务
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download1) object:nil];
// 2.执行操作(默认情况下,如果操作没有放到操作队列中,同步执行)
[operation start];
}
-(void)download1
{
NSLog(@"下载1----%@",[NSThread currentThread]);
}
结果如下:

可以看出,默认情况下,如果操作没有放到操作队列中,会在主线程同步执行,只有讲NSOperation放到NSOperationQueue中才会异步执行。
二、NSBlockOperation
- (void)viewDidLoad {
[super viewDidLoad];
[self blockOperation];
}
- (void)blockOperation
{
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"NSBlockOperation--下载1---%@",[NSThread currentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"NSBlockOperation--下载2---%@",[NSThread currentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"NSBlockOperation--下载3---%@",[NSThread currentThread]);
}];
[operation start];
}
结果如图:

我们会发现,NSBlockOperation当只有单个任务的时候,也是默认在主线程执行,当任务数大于1的时候,会开启子线程并发执行其它的操作
三、配合使用NSOperationQueue
- (void)viewDidLoad {
[super viewDidLoad];
[self operationQueue];
}
- (void)operationQueue
{
NSInvocationOperation *operation1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download1) object:nil];
NSInvocationOperation *operation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download2) object:nil];
NSInvocationOperation *operation3 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download3) object:nil];
NSBlockOperation *operation4 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"NSBlockOperation--1---%@",[NSThread currentThread]);
}];
[operation4 addExecutionBlock:^{
NSLog(@"NSBlockOperation--2---%@",[NSThread currentThread]);
}];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation1];
[queue addOperation:operation2];
[queue addOperation:operation3];
[queue addOperation:operation4];
}
-(void)download1
{
NSLog(@"下载1----%@",[NSThread currentThread]);
}
-(void)download2
{
NSLog(@"下载2----%@",[NSThread currentThread]);
}
-(void)download3
{
NSLog(@"下载3----%@",[NSThread currentThread]);
}
结果如下

可以看出,只要是添加到NSOperationQueue中的操作,系统都会自动为我们开启子线程来执行,并且是并发无序的执行,和添加的顺序无关。
然而有些时候我们需要明确地指定操作的顺序,我们可以在NSOperation之间设置依赖来保证执行顺序。
比如操作1要在操作2后面执行,可以这么写:[operation1 addDependency:operation2] 意思是operation1依赖于operation2,也就是operation1要在operation2后面执行
上代码验证下:
- (void)viewDidLoad {
[super viewDidLoad];
[self operationQueue];
}
- (void)operationQueue
{
NSInvocationOperation *operation1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download1) object:nil];
NSInvocationOperation *operation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download2) object:nil];
NSInvocationOperation *operation3 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download3) object:nil];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[operation3 addDependency:operation1];
[operation1 addDependency:operation2];
[queue addOperation:operation1];
[queue addOperation:operation2];
[queue addOperation:operation3];
}
-(void)download1
{
NSLog(@"下载1----%@",[NSThread currentThread]);
}
-(void)download2
{
NSLog(@"下载2----%@",[NSThread currentThread]);
}
-(void)download3
{
NSLog(@"下载3----%@",[NSThread currentThread]);
}
结果如下:

操作顺序Operation2->Operation1->Operation3,完全正确,其实就是谁依赖谁,谁就在它的后面执行
另外也可以在不同queue的NSOperation之间设置依赖

操作顺序:4->3->2->1 其余两个并发执行
下面列出了NSOperationQueue的一些属性和方法:
1.- (void)cancelAllOperations 取消队列的所有操作。PS:也可以调用NSOperation的-(void)cancel方法取消单个操作
2.@property (getter=isSuspended) BOOL suspended;YES表示暂停队列,NO表示回复队列
3.@property NSInteger maxConcurrentOperationCount;表示最大并发数,一般不大于5
四、自定义NSOperation
当将自定义的NSOperation添加到NSOperationQueue的时候,系统会调用NSOperation的-(void)main方法,所以我们只要重写这个方法实现相应的实现即可。
-(void)main
{
@autoreleasepool { // 异步线程无法访问主线程的自动释放池,需要自己添加
if (self.isCancelled) return;// 时刻监听操作是否取消,若取消就返回
NSURL *url = [NSURL URLWithString:self.matchUrl];
if (self.isCancelled) return;
NSData *data = [NSData dataWithContentsOfURL:url];
if (self.isCancelled) return;
UIImage *image = [UIImage imageWithData:data];
if ([_delegate respondsToSelector:@selector(operation:finshedDownloadImage:)]) {
dispatch_async(dispatch_get_main_queue(), ^{// 在主线程更新UI
[self.delegate operation:self finshedDownloadImage:image];
});
}
}
}
注意由于子线称无法访问主线程的自动释放池,所以需要自己添加。
下面是个小Demo截图,自定义NSOperation实现图片的异步下载,以及避免重复下载同一张图片

iOS多线程--NSOperation的更多相关文章
- iOS 多线程 NSOperation、NSOperationQueue
1. NSOperation.NSOperationQueue 简介 NSOperation.NSOperationQueue 是苹果提供给我们的一套多线程解决方案.实际上 NSOperation.N ...
- iOS多线程 NSOperation的用法
上一篇写了 GCD 的使用,接下来就了解一下 NSOperation ,NSOperation是苹果对 GCD 的 OC 版的一个封装,但是相对于GCD来说可控性更强,并且可以加入操作依赖. NSOp ...
- iOS多线程--NSOperation 浅显易懂
NSOperation是基于GCD的一套多线程实现方案,和GCD一样,线程的生命周期是由系统来自动管理的,不用像NSThread和Pthread一样让程序员手动管理.相对于GCD来说,它更加地面向对象 ...
- iOS多线程---NSOperation介绍和使用
1. NSOperation实现多线程编程,需要和NSOperationQueue一起使用. (1)先将要执行的操作封装到NSOperation中 (2)将NSOperation对象添加到NSOpe ...
- IOS 多线程 NSOperation GCD
1.NSInvocationOperation NSInvocationOperation * op; NSOperationQueue * que = [[NSOperationQueuealloc ...
- iOS多线程---NSOperation的常用操作
1.最大并发数: - (NSInteger)maxConcurrentOperationCount;- (void)setMaxConcurrentOperationCount:(NSInteger) ...
- iOS多线程编程
废话不多说,直接上干货.先熟悉一下基本知识,然后讲一下常用的两种,NSOperation和GCD. 一.基础概念 进程: 狭义定义:进程是正在运行的程序的实例(an instance of a com ...
- iOS GCD NSOperation NSThread等多线程各种举例详解(拷贝)
2年多的iOS之路匆匆而过,期间也拜读来不少大神的博客,近来突然为自己一直做伸手党感到羞耻,是时候回馈社会.回想当年自己还是小白的时候,照着一些iOS多线程教程学,也只是照抄,只知其然.不知其所以然. ...
- iOS 多线程学习笔记 —— NSOperation
本文复制.参考自文章:iOS多线程编程之NSOperation和NSOperationQueue的使用 ,主要为了加强个人对知识的理解和记忆,不做他用.原作者声明: 著作权声明:本文由http://b ...
随机推荐
- C++类型引用浅析
C++类型引用浅析 引言 从最早被Bjarne Stroustrup 发明,作为C语言的扩展,到广为人知C++98标准,再到最新的C++11.C++14和C++17标准,C++一直在不断地进步.演化. ...
- 【原】Windows中使用Redis基本入门教程
Redis是c编写基于Unix平台开发的一种内存KV数据库,官网上并没有给出Window的安装包,但MS基于redis发布了Windows版本. 下载链接: https://github.com/MS ...
- 《HTML5与CSS3基础教程》笔记
以下笔记摘要页码基于 人民邮电出版社 2013年1月第1版 英文书名:HMTL5 and CSS3 Visual Quickstart Guide (Seven Edition) 前言 P2: 渐进增 ...
- 代码-Weka的决策树类J48
package kit.weka; /** * desc:试试Weka的决策树类 * <code>J48Test</code> * */ import java.io.Fi ...
- 教程-隐藏/显示任务栏-程序不在任务显示-全面控制Windows
1.隐藏任务条 var h:THandle; //变量h:=FindWindow('Shell_TrayWnd',nil);ShowWindow(h,SW_hide); 2.显示任务条h:=Find ...
- java异常处理一
为什么需要异常处理? 郝斌解释:因为有些异常不能间接的利用if else来处理,比如说输入的时候,将键盘输入的内容转换为数字,此事如果用户输入非数字就会出现异常,而在用户输入之前是无法用程序判断用户所 ...
- IOS GCD 使用(一) 简介
一 GCD简介 GCD(Grand Central Dispatch)是苹果为实现并发编程提供的新技术.从基本功能上讲,GCD有点像NSOperationQueue,他们都允许程序将任务切分为多个单一 ...
- XML 语法规则
转摘自:http://www.w3school.com.cn/xml/xml_elements.asp XML 语法规则 XML 文档包含 XML 元素. XML 的语法规则很简单,且很有逻辑.这些规 ...
- spring + springmvc + jdbc + quartz + maven整合
个人搭建框架: pom.xml: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="htt ...
- 关于SpingMVC实现文件下载你所不知道的
http://www.cnblogs.com/yolanda-lee/p/4683422.html 文件的上传下载一般在项目中还是非常实用的,此处专门整理一下文件的下载,至于文件的上传实现将在后续中补 ...