iOS多线程理解之NSOperation

上一节有讲到过关于NSThread的方式实现多线程,本章将会采用NSOperation实现多线程。使用NSOperation去操作,相对较为简单,只需要将NSOperation放到NSOperationQueue这个队列中,线程就会依次的启动,NSOperationQueue负责管理,执行所有的NSOperation,可以更加方便容易的管理线程总的数量和线程之间的优先级关系。有效的解决NSThread中存在的问题。

在NSOperation中有两个常用子类用于创建线程的操作:

  • NSInvocationOperation
  • NSBlockOperation(block形式组织代码)

NSOperation

可以将其看做线程管理器,对线程进行管理操作。下面看一下其属性和方法

1
2
3
4
5
- (void)addOperation:(NSOperation *)op;//将创建的Operation放入操作队列,`添加到操作队列后,队列会开启一个新的线程执行此操作`
- (void)addOperationWithBlock:(void (^)(void))block NS_AVAILABLE(10_6, 4_0);//采用block的形式加入操作队列
@property NSInteger maxConcurrentOperationCount;////限制队列同时只运行线程的最大数量
- (void)cancelAllOperations;//取消当前队列的所有操作
.....

NSInvocationOperation

相对于使用NSThread代码减少,不需要管理其线程。

1
2
3
4
NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(loadImage:) object:model];
//创建完NSInvocationOperation对象并不会调用,它由一个start方法启动操作,但是注意如果直接调用start方法,则此操作会在主线程中调用,一般不会这么操作,而是添加到NSOperationQueue中
//[invocationOperation start];
[self.operationQueue addOperation:invocationOperation];//注意添加到操作队后,队列会开启一个线程执行此操作

NSBlockOperation

相对于NSInvocationOperation使用更加简单,直接使用block块。可以不必单独定义新的方法,直接在block中写代码即可。可以避免参数传递限制的问题。

1
2
3
4
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{//简洁,避免传递参数的问题
[self loadImage:model];
}];
[self.operationQueue addOperation:blockOperation];
使用NSOperation进行多线程开发可以设置最大并发线程,有效的对线程进行了控制。

线程执行顺序

在之前使用NSThread很难控制线程的执行顺序,但是在NSOperation中就相对比较容易控制,每一个NSOperation可以设置依赖线程,NSOperation提供了addDependency方法可以有效的控制当前queue中的线程之间的依赖关系。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//创建多个线程用于填充图片
for (int i=0; i<count-1; ++i) {
//方法1:创建操作块添加到队列
//创建多线程操作
NSBlockOperation *blockOperation=[NSBlockOperation blockOperationWithBlock:^{
[self loadImage:[NSNumber numberWithInt:i]];
}];
//设置依赖操作为最后一张图片加载操作
[blockOperation addDependency:lastBlockOperation];

[operationQueue addOperation:blockOperation];

}
//将最后一个图片的加载操作加入线程队列
[operationQueue addOperation:lastBlockOperation];

需要注意的是不可以设置为循环依赖,否则不会被执行。