文章目录
NSOperation、NSOperationQueue
NSOperation、NSOperationQueue是苹果提供给我们的一套多线程解决方案。
实际上NSOperation、NSOperationQueue是基于GCD更高一层的封装,完全面向对象。
比GCD更简单易用、代码可读性也更高
为什么要使用NSOperation、NSOperationQueue
- 可添加完成的代码块,在操作完成之后执行
NSOperation的completionBlock属性 - 添加操作之间的依赖关系,方便的控制执行顺序
- 设定操作执行的优先级
- 可以很方便的取消一个操作的执行
- 使用KVO观察对操作执行状态的更改executing、finished、cancelled
通过KVO的方式移除finished值为yes的NSOperation - 可设置最大并发操作数,来控制串行、并行
NSOperation、NSOperationQueue操作和操作队列
NSOperation是基于GCD的更高一层的封装,GCD中的一些概念同样适用于NSOperation、NSOperationQueue。
在NSOperation、NSOperationQueue中也有类似任务(操作)、队列(操作队列)的概念
- 操作(Operation)
-
- 执行操作的意思,就是在线程中执行的那段代码
-
- 在GCD中是放在Block中的。在NSOperation中,我们使用NSOperation子类NSInvocationOperation、NSBlockOperation,或者自定义子类来封装操作
- 操作队列(Operation Queues)
-
- 操作队列,即用来存放操作的队列。不同于GCD中的调度队列FIFO(先进先出)的原则。NSOperationQueue对于添加到队列中的操作,首先进入准备就绪的状态(就绪状态取决于与操作之间的依赖关系),然后进入就绪状态的这些操作,开始执行的顺序由操作之间的优先级决定。(优先级是操作对象自身的属性)
NSOperation、NSOperationQueue使用步骤
NSOperation实现多线程的使用步骤分为三步:
- 创建操作:先将需要执行的操作封装到一个NSOperation对象中
- 创建队列:创建NSOperationQueue对象
- 将操作加入到队列中:将NSOperation对象添加到NSOperationQueue对象中
之后,系统会自动将NSOperationQueue中的NSOperation取出来,在新线程中执行操作
NSOperation、NSOperation基本使用
创建操作
NSOperation是个抽象类,不能创建实例,不能用来封装操作。我们只能要他的子线程来封装操作。有三种方式来封装操作。
- 使用子类NSInvocationOperation
- 使用子类NSBlockOperation
- 自定义继承自NSOperation的子类,通过实现内部相应的方法来封装操作
使用子类NSInvocationOperation
- 在没有使用NSOperationQueue、在主线程中使用子类NSInvocationOperation执行一个操作的情况下,操作时在当前线程中执行的。并没有开启新线程。
- 如果在其他线程中执行操作,则打印的结果为其他线程
- 在其他线程中单独使用子类NSInvocationOperation,操作是在这个其他线程中执行的,并没有开启新线程
使用子类NSBlockOperation
- 可以看到在没有使用NSOperationQueue、在主线程中单独使用NSBlockOperation执行一个操作的情况下,操作是在当前线程执行的,没有开启新线程。
当然,如果是在其他线程使用NSBlockOperation执行一个操作,打印结果就为其他线程。同样也没有开启新线程。
NSBlockOperation还有一个方法addExecutionBlock:
,通过addExecutionBlock:
就可以为NSBlockOperation添加额外的操作。这些操作(包括blockOperationWithBlock中的操作)可以在不同的线程中同时(并发)执行。只有当所有相关的操作已经完成执行时,才视为完成。
如果添加的操作多的话,blockOperationWithBlock:中的操作也有可能会在其他线程(非当前线程)中执行,这是由系统决定的,并不是说添加到blockOperationWithBlock:中的操作一定在当前线程中执行。
- (void)useBlockOperation {
NSLog(@"%@", [NSThread currentThread]);
//1 创建NSBlockOperation对象
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
int i = 2;
while (i--) {
[NSThread sleepForTimeInterval:2];
NSLog(@"Block task, %@", [NSThread currentThread]);
}
}];
//2 添加额外的操作
[op addExecutionBlock:^{
[NSThread sleepForTimeInterval:2];
NSLog(@"1--Block task, %@", [NSThread currentThread]);
}];
[op addExecutionBlock:^{
[NSThread sleepForTimeInterval:2];
NSLog(@"2--Block task, %@", [NSThread currentThread]);
}];
[op addExecutionBlock:^{
[NSThread sleepForTimeInterval:2];
NSLog