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:

 1 - (void)viewDidLoad {
2 [super viewDidLoad];
3 [self invocationOperation];
4 }
5
6 -(void)invocationOperation
7 {
8
9 // 1.创建操作对象,封住需要执行的任务
10 NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download1) object:nil];
11
12 // 2.执行操作(默认情况下,如果操作没有放到操作队列中,同步执行)
13 [operation start];
14 }
15
16 -(void)download1
17 {
18 NSLog(@"下载1----%@",[NSThread currentThread]);
19 }

结果如下:

可以看出,默认情况下,如果操作没有放到操作队列中,会在主线程同步执行,只有讲NSOperation放到NSOperationQueue中才会异步执行。

二、NSBlockOperation

 1 - (void)viewDidLoad {
2 [super viewDidLoad];
3 [self blockOperation];
4 }
5
6 - (void)blockOperation
7 {
8 NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
9 NSLog(@"NSBlockOperation--下载1---%@",[NSThread currentThread]);
10 }];
11
12 [operation addExecutionBlock:^{
13 NSLog(@"NSBlockOperation--下载2---%@",[NSThread currentThread]);
14 }];
15
16 [operation addExecutionBlock:^{
17 NSLog(@"NSBlockOperation--下载3---%@",[NSThread currentThread]);
18 }];
19 [operation start];
20 }

结果如图:

我们会发现,NSBlockOperation当只有单个任务的时候,也是默认在主线程执行,当任务数大于1的时候,会开启子线程并发执行其它的操作

三、配合使用NSOperationQueue

 1 - (void)viewDidLoad {
2 [super viewDidLoad];
3 [self operationQueue];
4 }
5
6 - (void)operationQueue
7 {
8 NSInvocationOperation *operation1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download1) object:nil];
9 NSInvocationOperation *operation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download2) object:nil];
10 NSInvocationOperation *operation3 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download3) object:nil];
11 NSBlockOperation *operation4 = [NSBlockOperation blockOperationWithBlock:^{
12 NSLog(@"NSBlockOperation--1---%@",[NSThread currentThread]);
13 }];
14 [operation4 addExecutionBlock:^{
15 NSLog(@"NSBlockOperation--2---%@",[NSThread currentThread]);
16 }];
17 NSOperationQueue *queue = [[NSOperationQueue alloc] init];
18 [queue addOperation:operation1];
19 [queue addOperation:operation2];
20 [queue addOperation:operation3];
21 [queue addOperation:operation4];
22 }
23 -(void)download1
24 {
25 NSLog(@"下载1----%@",[NSThread currentThread]);
26 }
27 -(void)download2
28 {
29 NSLog(@"下载2----%@",[NSThread currentThread]);
30 }
31 -(void)download3
32 {
33 NSLog(@"下载3----%@",[NSThread currentThread]);
34 }

结果如下

可以看出,只要是添加到NSOperationQueue中的操作,系统都会自动为我们开启子线程来执行,并且是并发无序的执行,和添加的顺序无关。

然而有些时候我们需要明确地指定操作的顺序,我们可以在NSOperation之间设置依赖来保证执行顺序。

比如操作1要在操作2后面执行,可以这么写:[operation1 addDependency:operation2] 意思是operation1依赖于operation2,也就是operation1要在operation2后面执行

上代码验证下:

 1 - (void)viewDidLoad {
2 [super viewDidLoad];
3 [self operationQueue];
4 }
5
6 - (void)operationQueue
7 {
8 NSInvocationOperation *operation1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download1) object:nil];
9 NSInvocationOperation *operation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download2) object:nil];
10 NSInvocationOperation *operation3 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download3) object:nil];
11 NSOperationQueue *queue = [[NSOperationQueue alloc] init];
12 [operation3 addDependency:operation1];
13 [operation1 addDependency:operation2];
14 [queue addOperation:operation1];
15 [queue addOperation:operation2];
16 [queue addOperation:operation3];
17 }
18 -(void)download1
19 {
20 NSLog(@"下载1----%@",[NSThread currentThread]);
21 }
22 -(void)download2
23 {
24 NSLog(@"下载2----%@",[NSThread currentThread]);
25 }
26 -(void)download3
27 {
28 NSLog(@"下载3----%@",[NSThread currentThread]);
29 }

结果如下:

操作顺序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方法,所以我们只要重写这个方法实现相应的实现即可。

 1 -(void)main
2 {
3 @autoreleasepool { // 异步线程无法访问主线程的自动释放池,需要自己添加
4 if (self.isCancelled) return;// 时刻监听操作是否取消,若取消就返回
5 NSURL *url = [NSURL URLWithString:self.matchUrl];
6 if (self.isCancelled) return;
7 NSData *data = [NSData dataWithContentsOfURL:url];
8 if (self.isCancelled) return;
9 UIImage *image = [UIImage imageWithData:data];
10 if ([_delegate respondsToSelector:@selector(operation:finshedDownloadImage:)]) {
11 dispatch_async(dispatch_get_main_queue(), ^{// 在主线程更新UI
12 [self.delegate operation:self finshedDownloadImage:image];
13 });
14 }
15 }
16 }

注意由于主线称无法访问主线程的自动释放池,所以需要自己添加。

下面是个小Demo截图,自定义NSOperation实现图片的异步下载,以及避免重复下载同一张图片

iOS多线程--NSOperation 浅显易懂的更多相关文章

  1. iOS 多线程 NSOperation、NSOperationQueue

    1. NSOperation.NSOperationQueue 简介 NSOperation.NSOperationQueue 是苹果提供给我们的一套多线程解决方案.实际上 NSOperation.N ...

  2. iOS多线程 NSOperation的用法

    上一篇写了 GCD 的使用,接下来就了解一下 NSOperation ,NSOperation是苹果对 GCD 的 OC 版的一个封装,但是相对于GCD来说可控性更强,并且可以加入操作依赖. NSOp ...

  3. iOS多线程--NSOperation

    NSOperation是基于GCD的一套多线程实现方案,和GCD一样,线程的生命周期是由系统来自动管理的,不用像NSThread和Pthread一样让程序员手动管理.相对于GCD来说,它更加地面向对象 ...

  4. iOS多线程---NSOperation介绍和使用

    1.  NSOperation实现多线程编程,需要和NSOperationQueue一起使用. (1)先将要执行的操作封装到NSOperation中 (2)将NSOperation对象添加到NSOpe ...

  5. IOS 多线程 NSOperation GCD

    1.NSInvocationOperation NSInvocationOperation * op; NSOperationQueue * que = [[NSOperationQueuealloc ...

  6. iOS多线程---NSOperation的常用操作

    1.最大并发数: - (NSInteger)maxConcurrentOperationCount;- (void)setMaxConcurrentOperationCount:(NSInteger) ...

  7. iOS多线程编程

    废话不多说,直接上干货.先熟悉一下基本知识,然后讲一下常用的两种,NSOperation和GCD. 一.基础概念 进程: 狭义定义:进程是正在运行的程序的实例(an instance of a com ...

  8. iOS GCD NSOperation NSThread等多线程各种举例详解(拷贝)

    2年多的iOS之路匆匆而过,期间也拜读来不少大神的博客,近来突然为自己一直做伸手党感到羞耻,是时候回馈社会.回想当年自己还是小白的时候,照着一些iOS多线程教程学,也只是照抄,只知其然.不知其所以然. ...

  9. iOS 多线程学习笔记 —— NSOperation

    本文复制.参考自文章:iOS多线程编程之NSOperation和NSOperationQueue的使用 ,主要为了加强个人对知识的理解和记忆,不做他用.原作者声明: 著作权声明:本文由http://b ...

随机推荐

  1. 1.3 ASP.NET MVC生命周期

    ASP.NET MVC的执行生命周期主要分为三个阶段,分别是网址路由对比.执行控制器与动作.执行视图并返回结果.从ASP.NET MVC接受HTTP请求到返回HTTP响应的过程如下图所示.

  2. 笔记8:winfrom连接数据库DBHelp

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.D ...

  3. 减少HTTP请求之将图片转成二进制并生成Base64编码,可以在网页中通过url查看图片(大型网站优化技术)

    在网站开发过程中,对于页面的加载效率一般都想尽办法求快.那么,怎么让才能更快呢?减少页面请求 是一个优化页面加载速度很好的方法.上一篇博文我们讲解了 “利用将小图标合成一张背景图来减少HTTP请求”, ...

  4. DOM之兄弟节点

    <!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head>    < ...

  5. 10+优秀“分步引导”jQuery插件(转)

    很 多时候一个网站或者一个Web应用出品,为了让你的用户知道你的站点(或应用)有些什么?如何操作?为了让你的用户有更好的体验.往往这个时候都会给你的 站点(应用)添加一个分步指引的效果.然而这样的效果 ...

  6. Div CSS absolute与relative的区别小结

    absolute:绝对定位,CSS 写法“ position: absolute; ”,它的定位分两种情况,如下: 1. 没有设定 Top.Right.Bottom.Left 的情况,默认依据父级的“ ...

  7. linux shell中,单引号、 双引号,反引号(``),$()的区别

    一.单引号和双引号 首先,单引号和双引号,都是为了解决中间有空格的问题. 空格在linux中时作为一个很典型的分隔符,比如 string1=this is a string,这样执行会报错.为了避免这 ...

  8. BZOJ4000 [TJOI2015]棋盘

    首先是状态压缩DP... 然后我们发现转移都是一样的...可以矩阵优化... 于是做完啦QAQQQ 题目读不懂?恩多读几遍就读懂了,诶诶诶!别打我呀! /*********************** ...

  9. JDE910笔记2--OMW项目建立及简单使用[转]

    1.打开JDE的OBJECT MANAGEMENT WORKBENCH.在工作区中选择ADD,建立项目并选择OMW PROJECT,添加相关信息,如下图所示 其中,ProjectID可以对应不同的数据 ...

  10. 查询使用NoLock

    当我们在操作数据库的时候,无论是查询还是修改数据库的操作我们都习惯使用using(var db=new XXXDB()){},但是如果仅仅是做查询,最好是使用NoLock,因为NoLock使用的是共享 ...