哈喽,每日分享时间。今天要说说的是NSOperation这个类,以及和GCD的关系和区别
事不宜迟
1.NSOperation是什么?
我们知道,GCD是基于底层C语言封装的API。那么NSOperation是什么呢?
"灯灯灯灯" 揭晓答案
NSOperation实际上是基于GCD的Objective-C语言封装的对象。也就是所谓的父子关系。
既然是父子关系,俩者肯定有区别
那么区别是什么呢?
1.GCD是无法取消加入到队列中的任务的,而NSOperation则可以取消未运行任务。注意是未运行。
2.GCD队列任务运行顺序是先进先出(FIOI)也就是先进队列的任务先执行,而NSOperation可以随意调配任务执行顺序。
备注:GCD任务虽然也可以进行调配,但是需要复杂繁琐的代码及功能块进行控制(barrier、group等)
3.NSOperation任务支持KVO(监听),可以方便监听任务状态(开始,执行中,结束等),而GCD则不支持。
4.NSOperation可以设置同一队列中的任务优先级,也可以设置并发任务的执行顺序。GCD只能设置不同队列的执行优先级
5.NSOperation支持自定义,可以封装繁琐复杂任务代码,提高复用性。GCD则不能。
2.NSOperation怎么用?
1.NSOperation本身是不能直接使用的抽象类。可以通过使用系统自带的子类NSInvocationOperation/NSBlockOperation,或则是使用自行封装的Operation子类。
2.Operation对象都是调用start方法执行任务的。也有例外,比如说"NSOperationQueue"
例:
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector('对象方法') object:nil]; [op start];
那么子类NSInvocationOperation/NSBlockOperation 俩者又有何区别?
1.当单独使用NSInvocationOperation时,NSInvocationOperation是在主线程进行操作,并且没有开启新线程。使用的是同步执行的方式。
2.当使用NSBlockOperation时,NSBlockOperation是在主线程进行同步执行操作。新增子线程进行并发执行操作。
对的没错是本体,NSBlockOperation本身具备添加子线程方法"addExeutionBlock"。以下是例子。
['实例对象' addExecutionBlock:^{ //方法 }];
大致讲完子类,我们来说说另外一种启动方式:NSOperationQueue
如果不用start启动NSOperation子类进行操作任务的话,也可以通过将子类对象直接添加到操作对象队列中直接执行任务,并且默认开启新线程,执行的是并发操作。
直接添加的方式有俩种以下代码示例~~
//通过方法添加 //<1> :- (void)addOperation:(NSOperation *)op; ["实例的队列对象" addOperation:"Op对象"]; //通过block直接添加 // <2>: - (void)addOperationWithBlock:(void (^)(void))block; ["实例的队列对象" addOperationWithBlock:^{ }];
3.NSOperation还有什么用?
1.添加依赖
NSOperation可以通过添加依赖来操作对象的先后执行顺序。
添加方法:addDependency:
删除方法:removeDependency:
例: 假设任务一依赖于任务二
['任务1' addDeperdency:'任务2'];
添加依赖后,此时的任务1需要在任务2执行完毕后,才会执行。
注意事项:
1.如果任务出现互相依赖的情况,那么程序将会陷入死循环loop。
2.当被依赖的任务2未执行的情况下,执行任务1时。程序将会运行失败,并且报错。
3.依赖关系必须在任务添加到队列前才会有效。
4.添加依赖的操作对象必须等待所有操作完成时(操作在未运行的情况下被取消也算作完成),才会执行操作。
2.取消
NSOperation可以通过指令来取消对象未执行的操作。注意,是未 执 行。已执行、操作中的对象是不能被取消的。
//单项取消未 执 行 操作 ['任务1' cancel]; //取消所有未执行的操作 ['线程' cancelAllOperation];
3.优先级
NSOperation可以通过优先级指令来设定同一队列的操作顺序先后。
//这是优先级函数 typedef NS_ENUM(NSInteger, NSOperationQueuePriority) { NSOperationQueuePriorityVeryLow = -8L, NSOperationQueuePriorityLow = -4L, NSOperationQueuePriorityNormal = 0, NSOperationQueuePriorityHigh = 4, NSOperationQueuePriorityVeryHigh = 8 }; //这是使用方法 ['任务1' setOperationPriorty:NSOperationQueuePriorityNormal];
注意事项:操作优先级并不是绝对优先的,还需要看当前操作的依赖关系以及操作加入队列的顺序。当加入的操作依赖关系未处理,或者晚于同优先级操作进入队列时,当前操作将会延后处理。
4.暂停、继续
NSOperation可以通过指令简单的阻止新操作的执行,并且不会打断正在执行的操作。
//这是代码 queue代表当前线程 //暂停 [self.queue setSuspendecl:YES]; //结束暂停 [self.queue setSuspendecl:NO];
5.监听状态
NSOperation的操作对象中,开发者提供了以下五种监听状态给开发者
1.isExcuting ,该状态代表任务执行中。
2.isFinished ,该状态代表任务结束。当isFinished = YES时,其他依赖操作队列才会开始执行。操作队列也是根据这状态判断决定是否将操作任务移出队列
3.isCancel ,该状态代表任务已经取消执行。
4.isAsynchronours ,该状态表示任务是同步执行还是异步执行。
5.isReady ,该状态表示任务准备中,一般作用于有依赖任务的任务。一般isReady = NO。当依赖任务isFinished = Yes时,isReady 才会将当前状态改为YES;
学习总结:
即使说NSOperation功能众多而且便利,但是多数多线程操作一般都交于GCD处理,因为GCD更靠近底层代码,速度快这是关键。只有部分特殊要求(取消任务、设置任务执行顺序、监听任务状态、封装任务操作等)才会用到。
over~