NSOperation的介绍


iOS开发多线程篇—NSOperation简单介绍

一、NSOperation简介
1. 简单说明
a. NSOperation的作用:
是OC语言中基于GCD的面向对象的封装,使用起来比GCD更加简单(面向对象);
提供了一些用GCD不好实现的功能,使用NSOperation不用关心线程以及线程的生命周期(苹果推荐使用)。

b. 配合使用NSOperation和NSOperationQueue实现多线程编程的具体步骤:

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

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

(3)系统会⾃动将NSOperationQueue中的NSOperation取出来

(4)将取出的NSOperation封装的操作放到⼀条新线程中执⾏

c. NSOperation的子类

NSOperation是一个抽象类,不能直接使用(方法没有实现),约束子类都具有共同的属性和方法,并不具备封装操作的能力,必须使⽤它的子类。
使用NSOperation⼦类的方式有3种:
(1)NSInvocationOperation
(2)NSBlockOperation
(3)自定义子类继承NSOperation,实现内部相应的⽅法

2. 具体说明
2.1 NSInvocationOperation子类不常用
创建对象和执行操作:
 //创建操作对象,封装要执行的任务
 //NSInvocationOperation 封装操作
  NSInvocationOperation *operation=[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(test) object:nil];
//执行操作
   [operation start];

注意:操作对象默认在主线程中执行,只有添加到队列中才会开启新的线程。即默认情况下,如果操作没有放到队列中queue中,都是同步执行。只有将NSOperation放到一个NSOperationQueue中,才会异步执行操作,不常用!

2.2 NSBlockOperation子类
注意:只要NSBlockOperation封装的操作数 > 1,就会异步执行操作。
创建对象和添加操作:
//创建NSBlockOperation操作对象
  NSBlockOperation *operation=[NSBlockOperation blockOperationWithBlock:^{
      NSLog(@"NSBlockOperation1------%@",[NSThread currentThread]);
           }];
 //通过addExecutionBlock:方法添加更多的操作
 [operation addExecutionBlock:^{
     NSLog(@"NSBlockOperation2------%@",[NSThread currentThread]);
           }];
[operation start];
打印结果:
2015-10-26 14:06:11.765 test1[7036:326837] NSBlockOperation1------<NSThread: 0x7f8628e074d0>{number = 1, name = main}
2015-10-26 14:06:11.767 test1[7036:326882] NSBlockOperation2------<NSThread: 0x7f8628e2ef10>{number = 2, name = (null)}

2.3 NSOperationQueue
NSOperation可以调⽤start⽅法来执⾏任务,但默认是同步执行的。
如果将NSOperation添加到NSOperationQueue(操作队列)中,系统会自动异步执行NSOperation中的操作。
也就是说添加操作到NSOperationQueue中,自动执行操作,自动开启线程。

添加操作到NSOperationQueue中的两种那个方法:
 - (void)addOperation:(NSOperation *)op;
- (void)addOperationWithBlock:(void (^)(void))block;

注意:系统自动将NSOperationqueue中的NSOperation对象取出,将其封装的操作放到一条新的线程中执行,这些任务是并行执行的。
提示:队列的取出是有顺序的,与打印结果并不矛盾。这就好比,选手A,B,C虽然起跑的顺序是先A,后B,然后C,但是到达终点的顺序却不一定是A,B在前,C在后。

下面使用for循环打印,可以更明显的看出任务是并发执行的。
代码示例:
//创建NSInvocationOperation对象,封装操作
   
NSInvocationOperation *operation1=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(test1) object:nil];
   
NSInvocationOperation *operation2=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(test2) object:nil];
   
//创建NSBlockOperation对象,封装操作
   
NSBlockOperation *operation3=[NSBlockOperation blockOperationWithBlock:^{
       
for (int i=0; i<5; i++) {
           
NSLog(@"NSBlockOperation3--1----%@",[NSThread currentThread]);
        }
    }];
    [operation3
addExecutionBlock:^{
       
for (int i=0; i<5; i++) {
           
NSLog(@"NSBlockOperation3--2----%@",[NSThread currentThread]);
        }
    }];
   
//创建NSOperationQueue
   
NSOperationQueue * queue=[[NSOperationQueue alloc]init];
   
//把操作添加到队列中
    [queue
addOperation:operation1];
    [queue
addOperation:operation2];
    [queue
addOperation:operation3];
}
-(void)test1
{
   
for (int i=0; i<5; i++) {
       
NSLog(@"NSInvocationOperation1--%@",[NSThread currentThread]);
    }
}
-(void)test2
{
   
for (int i=0; i<5; i++) {
       
NSLog(@"NSInvocationOperation2--%@",[NSThread currentThread]);
    }
}
打印结果:

二、NSOperation 和 GCD 的比较
1. GCD
a.     GCD是iOS4.0 推出的,主要针对多核cpu做了优化,是C语言的技术;
b.     GCD是将任务(block)添加到队列(串行/并行/全局/主队列),并且以同步/异步的方式执行任务的函数;
c.     GCD提供了一些NSOperation不具备的功能
     1)一次性执行
     2)延迟执行
     3)调度组

2.  NSOperation
a.     NSOperation是iOS2.0推出的,iOS4之后重写了NSOperation;
b.     NSOperation将操作(异步的任务)添加到队列(并发队列),就会执行指定的操作;
c.     NSOperation里提供了方便的操作:
1)最大并发数:同时执行的任务数。
比如,同时开3个线程执行3个任务,并发数就是3。
最大并发数的相关方法
- (NSInteger)maxConcurrentOperationCount;
- (void)setMaxConcurrentOperationCount:(NSInteger)cnt;
示例:
-(NSOperationQueue *)queue {
   
if(!_queue){
       
_queue =[[NSOperationQueue alloc] init];
        //设置对大并发数
        _queue.maxConcurrentOperationCount = 3;
    }
   
return _queue;
}
2)队列的暂定/继续,
// YES代表暂停队列,NO代表恢复队列。
- (void)setSuspended:(BOOL)b; 
- (BOOL)isSuspended;
3)取消队列的所有操作
- (void)cancelAllOperations;
提示:也可以调用NSOperation的- (void)cancel方法取消单个操作。
示例:
//暂停暂停的是队列中还没有被运行的操作,正在运行的操作不能被暂停;
//当队列为暂停的时候,往队列中加入操作,也不会运行。
- (IBAction)pauseClick:(id)sender {
   
NSLog(@"点击暂停");
    [
self.queue setSuspended:YES];
}
//继续
- (
IBAction)resumeClick:(id)sender {
   
NSLog(@"点击继续");
    [
self.queue setSuspended:NO];
}
//取消
- (
IBAction)cancelClick:(id)sender {
   
NSLog(@"点击取消");
    [
self.queue cancelAllOperations];
}
4)指定操作之间的依赖关系(GCD可以用同步实现)
a. NSOperation之间可以设置依赖来保证执行顺序,比如一定要让操作A执行完后,才能执行操作B,可以这么写:
// 操作B依赖于操作A
[operationB addDependency:operationA]; 
b. 可以在不同queue的NSOperation之间创建依赖关系。
c. 注意不能相互依赖,比如A依赖B,B依赖A。
示例:
-(void)demo{
    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
       
//模拟耗时操作
        [
NSThread sleepForTimeInterval:arc4random_uniform(3)];
       
NSLog(@"1.登陆 %@",[NSThread currentThread]);
    }];
    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        [
NSThread sleepForTimeInterval:arc4random_uniform(3)];
       
NSLog(@"2.扣费 %@",[NSThread currentThread]);
    }];
    NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        [
NSThread sleepForTimeInterval:arc4random_uniform(3)];
       
NSLog(@"3.下载 %@",[NSThread currentThread]);
    }];
    NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
       
NSLog(@"4.UI更新 %@",[NSThread currentThread]);
    }];
    //添加操作依赖,要在操作放到队列之前。
   
//操作依赖可以跨队列设置。
    [op2
addDependency:op1];
    [op3
addDependency:op2];
    [op4 addDependency:op3];
    [self.queue addOperations:@[op1,op2,op3] waitUntilFinished:NO];
    [[
NSOperationQueue mainQueue] addOperation:op4];
}
5)操作队列的优先级
设置NSOperation在queue中的优先级,可以改变操作的执行优先级。
操作的优先级,优先级高的操作不一定最先运行。
队列的优先级 ,优先级高的队列不一定比优先级低的队列先运行完,而是有更多的可能被执行到。

6)线程间通信:
子线程->主线程 
操作方式与GCD类似。
示例:
[self.queue addOperationWithBlock:^{
         //子线程:do something
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
         //主线程的任务,操作UI等
    }];
}];

此外:
有些操作任务如果在主线程完成,会严重的影响到用户体验,造成UI卡的现象。我们可以通过自定义NSOperation,新开线程,让加载图片的任务异步执行,来解决此问题。








发布了53 篇原创文章 · 获赞 5 · 访问量 4万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章