使用NSOperation和NSOperationQueue实现多线程编程

使用NSOperation和NSOperationQueue实现多线程编程,实现步骤大致是这样的:

1> 先将需要执行的操作封装到一个NSOperation对象中

2> 然后将NSOperation对象添加到NSOperationQueue中

3> 系统会自动将NSOperation中封装的操作放到一条新线程中执行

回到顶部

一、NSInvocationOperation

1 NSInvocationOperation *operation = [[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run:) object:@"mj"] autorelease];

2 [operation start];

* 第1行初始化了一个NSInvocationOperation对象,它是基于一个对象和selector来创建操作

* 第2行调用了start方法,紧接着会马上执行封装好的操作,也就是会调用self的run:方法,并且将@"mj"作为方法参数

* 这里要注意:默认情况下,调用了start方法后并不会开一条新线程去执行操作,而是在当前线程同步执行操作。只有将operation放到一个NSOperationQueue中,才会异步执行操作。

回到顶部

二、NSBlockOperation

1.同步执行一个操作

1 NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^(){

2         NSLog(@"执行了一个新的操作");

3 }];

4  // 开始执行任务

5 [operation start];

* 第1行初始化了一个NSBlockOperation对象,它是用一个Block来封装需要执行的操作

* 第2行调用了start方法,紧接着会马上执行Block中的内容

* 这里还是在当前线程同步执行操作,并没有异步执行

2.并发执行多个操作

1 NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^(){

2   NSLog(@"执行第1次操作,线程:%@", [NSThread currentThread]);

3 }];

4

5 [operation addExecutionBlock:^() {

6   NSLog(@"又执行了1个新的操作,线程:%@", [NSThread currentThread]);

7 }];

8

9 [operation addExecutionBlock:^() {

10   NSLog(@"又执行了1个新的操作,线程:%@", [NSThread currentThread]);

11 }];

12

13 [operation addExecutionBlock:^() {

14   NSLog(@"又执行了1个新的操作,线程:%@", [NSThread currentThread]);

15 }];

16

17 // 开始执行任务

18 [operation start];

* 第1行初始化了一个NSBlockOperation对象

* 分别在第5、9、13行通过addExecutionBlock:方法添加了新的操作,包括第1行的操作,一共封装了4个操作

* 在第18行调用start方法后,就会并发地执行这4个操作,也就是会在不同线程中执行

1 2013-02-02 21:38:46.102 thread[4602:c07] 又执行了1个新的操作,线程:<NSThread: 0x7121d50>{name = (null), num = 1}

2 2013-02-02 21:38:46.102 thread[4602:3f03] 又执行了1个新的操作,线程:<NSThread: 0x742e1d0>{name = (null), num = 5}

3 2013-02-02 21:38:46.102 thread[4602:1b03] 执行第1次操作,线程:<NSThread: 0x742de50>{name = (null), num = 3}

4 2013-02-02 21:38:46.102 thread[4602:1303] 又执行了1个新的操作,线程:<NSThread: 0x7157bf0>{name = (null), num = 4}

可以看出,每个操作所在线程的num值都不一样,说明是不同线程

回到顶部

三、NSOperation的其他用法

1.取消操作

operation开始执行之后, 默认会一直执行操作直到完成,我们也可以调用cancel方法中途取消操作

[operation cancel];

2.在操作完成后做一些事情

如果想在一个NSOperation执行完毕后做一些事情,就调用NSOperation的setCompletionBlock方法来设置想做的事情

operation.completionBlock = ^() {

NSLog(@"执行完毕");

};

当operation封装的操作执行完毕后,就会回调Block里面的内容

回到顶部

四、自定义NSOperation

如果NSInvocationOperation和NSBlockOperation不能满足需求,我们可以直接新建子类继承NSOperation,并添加任何需要执行的操作。如果只是简单地自定义NSOperation,只需要重载-(void)main这个方法,在这个方法里面添加需要执行的操作。

下面写个子类DownloadOperation来下载图片

1.继承NSOperation,重写main方法

DownloadOperation.h

#import <Foundation/Foundation.h>

@protocol DownloadOperationDelegate;

@interface DownloadOperation : NSOperation

// 图片的url路径

@property (nonatomic, copy) NSString *imageUrl;

// 代理

@property (nonatomic, assign) id<DownloadOperationDelegate> delegate;

- (id)initWithUrl:(NSString *)url delegate:(id<DownloadOperationDelegate>)delegate;

@end

// 图片下载的协议

@protocol DownloadOperationDelegate <NSObject>

- (void)downloadFinishWithImage:(UIImage *)image;

@end

DownloadOperation.m

1 #import "DownloadOperation.h"

2

3 @implementation DownloadOperation

4 @synthesize delegate = _delegate;

5 @synthesize imageUrl = _imageUrl;

6

7 // 初始化

8 - (id)initWithUrl:(NSString *)url delegate:(id<DownloadOperationDelegate>)delegate {

9     if (self = [super init]) {

10         self.imageUrl = url;

11         self.delegate = delegate;

12     }

13     return self;

14 }

15 // 释放内存

16 - (void)dealloc {

17     [super dealloc];

18     [_imageUrl release];

19 }

20

21 // 执行主任务

22 - (void)main {

23     // 新建一个自动释放池,如果是异步执行操作,那么将无法访问到主线程的自动释放池

24     @autoreleasepool {

25         // ....

26     }

27 }

28 @end

* 在第22行重载了main方法,等会就把下载图片的代码写到这个方法中

* 如果这个DownloadOperation是在异步线程中执行操作,也就是说main方法在异步线程调用,那么将无法访问主线程的自动释放池,所以在第24行创建了一个属于当前线程的自动释放池

2.正确响应取消事件

* 默认情况下,一个NSOperation开始执行之后,会一直执行任务到结束,就比如上面的DownloadOperation,默认会执行完main方法中的所有代码。

* NSOperation提供了一个cancel方法,可以取消当前的操作。

* 如果是自定义NSOperation的话,需要手动处理这个取消事件。比如,一旦调用了cancel方法,应该马上终止main方法的执行,并及时回收一些资源。

* 处理取消事件的具体做法是:在main方法中定期地调用isCancelled方法检测操作是否已经被取消,也就是说是否调用了cancel方法,如果返回YES,表示已取消,则立即让main方法返回。

* 以下地方可能需要调用isCancelled方法:

  • • 在执行任何实际的工作之前,也就是在main方法的开头。因为取消可能发生在任何时候,甚至在operation执行之前。
  • • 执行了一段耗时的操作之后也需要检测操作是否已经被取消

1 - (void)main {

2     // 新建一个自动释放池,如果是异步执行操作,那么将无法访问到主线程的自动释放池

3     @autoreleasepool {

4         if (self.isCancelled) return;

5

6         // 获取图片数据

7         NSURL *url = [NSURL URLWithString:self.imageUrl];

8         NSData *imageData = [NSData dataWithContentsOfURL:url];

9

10         if (self.isCancelled) {

11             url = nil;

12             imageData = nil;

13             return;

14         }

15

16         // 初始化图片

17         UIImage *image = [UIImage imageWithData:imageData];

18

19         if (self.isCancelled) {

20             image = nil;

21             return;

22         }

23

24         if ([self.delegate respondsToSelector:@selector(downloadFinishWithImage:)]) {

25             // 把图片数据传回到主线程

26             [(NSObject *)self.delegate performSelectorOnMainThread:@selector(downloadFinishWithImage:) withObject:image waitUntilDone:NO];

27         }

28     }

29 }

* 在第4行main方法的开头就先判断operation有没有被取消。如果被取消了,那就没有必要往下执行了

* 经过第8行下载图片后,在第10行也需要判断操作有没有被取消

* 总之,执行了一段比较耗时的操作之后,都需要判断操作有没有被取消

* 图片下载完毕后,在第26行将图片数据传递给了代理(delegate)对象

使用NSOperation和NSOperationQueue实现多线程编程,布布扣,bubuko.com

时间: 2024-09-29 06:09:32

使用NSOperation和NSOperationQueue实现多线程编程的相关文章

用NSOperation和NSOperationQueue实现多线程编程

1.上一讲简单介绍了NSThread的使用,虽然也可以实现多线程编程,但是需要我们去管理线程的生命周期,还要考虑线程同步.加锁问题,造成一些性能上的开销.我们也可以配合使用NSOperation和NSOperationQueue实现多线程编程,实现步骤大致是这样的: 1> 先将需要执行的操作封装到一个NSOperation对象中 2> 然后将NSOperation对象添加到NSOperationQueue中 3> 系统会自动将NSOperation中封装的操作放到一条新线程中执行 在此过

多线程编程 (2) -NSOperation

多线程编程 (2) -NSOperation 一.NSInvocationOperation 二.NSBlockOperation 三.NSOperation的其他用法 四.自定义NSOperation 1.上一讲简单介绍了NSThread的使用,虽然也可以实现多线程编程,但是需要我们去管理线程的生命周期,还要考虑线程同步.加锁问题,造成一些性能上的开销.我们也可以配合使用NSOperation和NSOperationQueue实现多线程编程,实现步骤大致是这样的: 1> 先将需要执行的操作封装

iOS多线程编程Part 2/3 - NSOperation

多线程编程Part 1介绍了NSThread以及NSRunLoop,这篇Blog介绍另一种并发编程技术:NSOPeration. NSOperation & NSOperationQueue 从头文件NSOperation.h来看接口是非常的简洁,NSOperation本身是一个抽象类,定义了一个要执行的工作,NSOperationQueue是一个工作队列,当工作加入到队列后,NSOperationQueue会自动按照优先顺序及工作的从属依赖关系(如果有的话)组织执行. NSOperation是

多线程编程2-NSOperation

NSThread,虽然也可以实现多线程编程,但是需要我们去管理线程的生命周期,还要考虑线程同步.加锁问题,造成一些性能上的开销.我们也可以配合使用NSOperation和NSOperationQueue实现多线程编程,实现步骤大致是这样的: 1> 先将需要执行的操作封装到一个NSOperation对象中 2> 然后将NSOperation对象添加到NSOperationQueue中 3> 系统会自动将NSOperation中封装的操作放到一条新线程中执行 在此过程中,我们根本不用考虑线程

多线程编程(三种方式)

一.NSThread DownloadFile是一个继承NSObject的类,当中的runDownload方法是需要放到线程中执行:ThreadDownload则是一个继承NSThread的子线程类,配合隐式创建线程的方式,执行threadD对象中的run:函数并传入字符串@"download3" // download DownloadFile *download = [[DownloadFile alloc] init]; // 动态创建线程 NSThread *downloadT

【iOS沉思录】NSThread、GCD、NSOperation多线程编程总结

OC中的多线程 OC中多线程根据封装程度可以分为三个层次:NSThread.GCD和NSOperation,另外由于OC兼容C语言,因此仍然可以使用C语言的POSIX接口来实现多线程,只需引入相应的头文件:#include <pthread.h>. NSThread NSThread是封装程度最小最轻量级的,使用更灵活,但要手动管理线程的生命周期.线程同步和线程加锁等,开销较大: NSThread的基本使用比较简单,可以动态创建初始化NSThread对象,对其进行设置然后启动:也可以通过NST

多线程编程(三)NSOperationQueue

本文我们来介绍一下多线程编程工具中的NSOperationQueue. 1. NSOperationQueue简介 配合使用NSOperation和NSOperationQueue也可以实现多线程编程.使用NSOperationQueue方式进行多线程编程,不能够像NSThread一样直接创建线程,也不需要管理,但是可以间接的干预线程,这也是该方式的优点.NSOperationQueue同时引入了Queue(队列)的概念,了解NSOperationQueue使用,首先要了解NSOperation

ios多线程之NSOperation和NSOperationQueue

NSOperation的作用 配合使用NSOperation和NSOperationQueue也能实现多线程编程 1.NSOperation和NSOperationQueue实现多线程的具体步骤 2.先将需要执行的操作封装到一个NSOperation对象中 3.然后将NSOperation对象添加到NSOperationQueue中 4.系统会自动将NSOperationQueue中的NSOperation取出来 5.将取出的NSOperation封装的操作放到一条新线程中执行 NSOperat

NSOperation、NSOperationQueue

NSOperation.NSOperationQueue NSOperation 和 NSOperationQueue 配合使用也能实现多线程. NSOperation 继承于 NSObject,是一种抽象类,并不具备封装操作的能力,必须使用它的子类. 使用 NSOperation 子类的三种方式: 1.NSBlockOperation: 2.NSInvocationOperation: 3.自定义 NSOperation,实现内部相应方法. NSOperation 和 NSOperationQ