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,新开线程,让加载图片的任务异步执行,来解决此问题。








1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值