iOS开发系列-NSOperation
概述
NSOperation是基于GCD的封装更加面向对象,在使用上也是有任务跟队列的概念,分别对应两个类NSOperation 、NSOperationQueue
NSOperation和NSOperationQueue实现多线程的具体步骤
- 现将需要执行的操作封装到一个NSOperation对象中。
- 然后将NSOperation对象添加到NSOperationQueue中
- 系统会自动将NSOperationQueue中的NSOperation取出来
- 将取出的NSOperation封装的操作放到一条线程中执行
NSOperation
NSOperation是一个抽象类,使用时候需要使用其子类。NSOperation总共有两个子类。
- NSInvocationOperation
- NSBlockOperation
开发中一般NSOperation子类通常与NSOperationQueue一起使用才能更好的开辟线程。
NSOperationQueue
NSOperation可以调用start方法类执行任务,但默认是同步的。如果将NSOperation添加到NSOperationQueue中执行,系统会自动异步执行NSOperation中的操作。
NSOperationQueue只用两种类型,分别是主队列跟非主队列(包含串行、并发)。两种队列的获取方式:
[NSOperationQueue mainQueue]; // 主队类
[[NSOperationQueue alloc] init]; // 非主队列
凡是添加到主队列的任务都是在主线程中执行。非主队列的任务会自动添加到子线程中执行。并发跟串行通过队列的maxConcurrentOperationCount决定。
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task) object:nil];
[queue addOperation:operation];
// [operation start];
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"------------%@", [NSThread currentThread]);
}];
// 添加额外的任务才会在子线程执行
[blockOperation addExecutionBlock:^{
NSLog(@"------------%@", [NSThread currentThread]);
}];
[queue addOperation:blockOperation];
// [blockOperation start];
}
- (void)task
{
NSLog(@"------------%@", [NSThread currentThread]);
}
一旦NSOperation添加进NSOperationQueue,无须调用NSOperation的start方法,内部自动回调用NSOperation的start。
开发中还可以自定义NSOperation的方式,重写main方法将任务封装进来。如果任务的代码比较多,在很多程序的很多地方都需要使用,建议采用这种方式。
#import "FMOperation.h"
@implementation FMOperation
- (void)main
{
// 封装任务
}
@end
NSOperationQueue的挂起和取消
设置NSOperationQueue的属性suspended为YES,内部的操作会暂停,在设置suspended为NO时内部的操作会恢复执行。
注意:当设置NSOperationQueue的suspended为YES时,当前的正在进行的NSOperation中任务会继续执行直到完毕后再暂停。
调用NSOperationQueue的cancelAllOperations方法相当于调用了内部所有NSOperation内部的cancel方法,一旦取消无法恢复。若想再次执行只能从新添加。
同样调用cancelAllOperations时执行到一半的NSOperationQueue是没办法中途停止下来直到该NSOperation执行完毕。
如果我们在自定义的NSOperation的main中封装了大量耗时的操作,苹果建议我们需要在任务中间做判断。提高性能
#import "FMOperation.h"
@implementation FMOperation
- (void)main
{
// 封装任务
for (NSInteger i=0; i<10000; i++) {
NSLog(@"download1-----------");
}
if (self.isCancelled) return;
for (NSInteger i=0; i<10000; i++) {
NSLog(@"download2-----------");
}
if (self.isCancelled) return;
for (NSInteger i=0; i<10000; i++) {
NSLog(@"download3-----------");
}
if (self.isCancelled) return;
}
@end
NSOperation的操作依赖和监听
默认情况下,添加进队列中操作并发执行时执行顺序是不可控的,这里可以通过设置依赖。并且可以跨队列设置NSOperation依赖。
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSBlockOperation *blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"---------------blockOperation1");
}];
NSBlockOperation *blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"---------------blockOperation2");
}];
NSBlockOperation *blockOperation3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"---------------blockOperation3");
}];
// 在添加之前设置依赖 让blockOperation3最后执行
[blockOperation3 addDependency:blockOperation1];
[blockOperation3 addDependency:blockOperation2];
[queue addOperation:blockOperation1];
[queue addOperation:blockOperation2];
[queue addOperation:blockOperation3];
}
通过Operation的completionBlock属性监听某个NSOoperation任务执行完毕。
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSBlockOperation *blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"---------------blockOperation1");
}];
NSBlockOperation *blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"---------------blockOperation2");
}];
NSBlockOperation *blockOperation3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"---------------blockOperation3");
}];
// 监听blockOperation2执行完毕
blockOperation2.completionBlock = ^{
// blockOperation2执行完毕
};
[queue addOperation:blockOperation1];
[queue addOperation:blockOperation2];
[queue addOperation:blockOperation3];
}
最新文章
- bzoj3380+3381+3382+3383 Usaco2004 Open
- 实战 ASP.NET Web API
- Command mvn jetty:run
- $.ajax等相关用法
- Cookie初识篇
- NET设计模式(2):单件模式(Singleton Pattern)[转载]
- 新 Netflix 开源门户
- 【原】spring boot添加cros全局过滤器
- [Swift]LeetCode869. 重新排序得到 2 的幂 | Reordered Power of 2
- Python内置函数(31)——id
- [UE4]VR手柄按键参考
- Modbus库开发笔记之六:Modbus RTU Master开发
- Ajax的实现及使用-原生对象
- spring quartz动态修改执行时间
- Python自动化开发 - Django基础
- 将Vue-cli搭建的项目改造成多页面应用时对项目结构和配置的调整
- PHP文件引入
- htm5本地存储方案——websql的封装
- PAT 1102 Invert a Binary Tree[比较简单]
- 6.046 Design and Analysis of Algorithms
热门文章
- PHP headers_list() 函数
- 归并排序c语言
- Jboss集群(五)--F5硬件负载均衡器双击热备 + Jboss集群终极实现
- 20130317 如何批量把文件名称写入txt文档
- 无法启动此程序,因为计算机中丢失api-ms-win-crt-runtime-l1-1-0.dll已解决
- USACO 2004 Open The Cow Lineup /// oj25965
- 在Logstash的配置文件中对日志事件进行区分
- OC开发系列-成员变量的作用域
- Vagrant安装步骤
- springmvc常用知识总结,不定期更新