iOS开发之多线程-- NSOperation使用简介(个人笔记)

 NSOperation使用简介  

1.操作 NSOperation 和操作队列 NSOperationQueue!

{

    1.NSOperation(操作)简介:

    

    NSOperation: // 本质是对 GCD 的封装, OC 语言.

    

    NSOperation GCD 的比较:

    

    GCD使用场合:

    一些简单的需求,简单的多线程操作. //简单高效

    

    NSOperation使用场合:

    各个操作之间有依赖关系,操作需要取消/暂停;需要限制同时执行的线程数量,让线程在某时刻停止/继续等.

    

    配合使用 NSOperation NSOperationQueue 也可以实现多线程.


    2.NSOperation使用:

    

    NSOperation: 抽象类,不能直接使用,需要使用其子类.

    

    抽象类:定义子类共有的属性和方法.// CAAnimation/CAPropertyAnimation...

    

    两个常用子类: NSInvocationOperation(调用) NSBlockOperation();

    

                两者没有本质区别,后者使用 Block 的形式组织代码,使用相对方便.

    

    自定义子类继承自 NSOperation,实现内部相应的方法. // 高级用法

}

2.NSBlockOperation, NSInvocationOperation的简单使用.

{

    1. 创建 NSInvocationOperation 对象

    

    // 创建 NSInvocationOperation

    NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(longTimeOperation:) object:@"op1"];

    

    //默认情况下,调用 start 方法之后,不会开启新线程,只会在当前线程执行操作.

    [op1 start];

    

    注意:只有将 NSOperation 放到一个 NSOperationQueue ,才会异步执行操作.

    

    2. 创建 NSBlockOperation 对象

    

    // 创建 NSBlockOperation

    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{

        NSLog(@"下载图片1---%@",[NSThread currentThread]);

    }];

    // 添加更多操作

    [op2 addExecutionBlock:^{

        NSLog(@"下载图片2---%@",[NSThread currentThread]);

    }];

    [op2 addExecutionBlock:^{

        NSLog(@"下载图片3---%@",[NSThread currentThread]);

    }];

    

    // 只要 NSBlockOperation 中封装的操作数 > 1, 调用start方法之后就会开启多条线程并发执行

    // 如果 NSBlockOperation 中封装的操作数 == 1,调用 start 方法之后,不会开启新线程,只会在当前线程执行操作

    [op2 start];

    

    注意: 只要 NSBlockOperation 中封装的操作数 > 1,就会异步执行这些操作.(将操作添加到 NSOperationQueue中或者直接调用 start方法都会开启多条线程异步执行).

}

3.将操作添加到队列中;

{

    NSOperation 可以调用 start 方法来执行任务,但默认是同步执行的.

    NSOperation 添加到 NSOperationQueue(操作队列) ,系统会自动异步执行NSOperationQueue中的操作.

    

    1.NSOperationQueue(操作队列):

    

    <1> 主队列

    [NSOperationQueue mainQueue] //获取主队列

    添加到"主队列"中的操作,都会放在主线程执行!

    

    <2>非主队列

    [[NSOperationQueue alloc] init]; //创建非主队列

    添加到"非主队列"中得操作,都会放在子线程中执行.

    

    2.使用: 添加操作到操作队列中.

    

    // 创建 NSInvocationOperation 操作

    NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(longTimeOperation:) object:@"op1"];

    

    // 创建 NSBlockOperation 操作

    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{

        NSLog(@"下载图片1---%@",[NSThread currentThread]);

    }];


    // 1.创建一个 NSOperationQueue

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    

    // 2.将操作添加到队列中.

    [queue addOperation:op1];

    [queue addOperation:op2];

    

    注意:另外一种添加操作到队列中的方法: block

    [queue addOperationWithBlock:^{

        NSLog(@"下载图片5---%@",[NSThread currentThread]);

    }];

    

    推荐使用: block // 简单. 自己哪个使用熟练就用哪个.

    

    注意:队列中任务的执行是无序的.

    

}

 4.常见用法 

1.设置操作依赖. 2.设置最大并发数.

{

    问题:是否可以让队列中的操作有序执行?

    

    回答上问题: ,设置操作依赖.

    

    1.NSOperation设置操作依赖: // 执行顺序: op1,op2,op3;

    

    // 操作op3依赖于操作op2;

    [op3 addDependency:op2];

    // 操作op2依赖于操作op1;

    [op2 addDependency:op1];

    

    注意:不能相互依赖.

    

    2.NSOperationQueue设置最大并发数.

    

    并发数:同时开启的线程数.

    

    // 创建操作队列

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    // 设置操作队列的最大并发数

    queue.maxConcurrentOperationCount = 3;

    [queue setMaxConcurrentOperationCount:3];

}


1.队列的取消/暂停/恢复  2.线程间通信. 注意问题:为毛要取消/恢复队列? 在什么时候用?

{

    1.NSOperationQueue 的取消/暂停/恢复

    

    // 取消操作 op1. 取消单个操作.

    [op1 cancel];

    // 取消所有操作,不会再次恢复

    [queue cancelAllOperations];

    // 暂停所有操作;注意,已经开始的操作不会暂停.

    [queue setSuspended:YES];

    // 重新开始所有操作

    [queue setSuspended:NO];

    

    :为毛要取消恢复队列? 在什么时候用?

    

    :1.为了内存管理,处理内存警告; 2.为了用户体验,保证滚动流畅.

    

    // 接收到内存警告的时候果断取消队列中的所有操作

    - (void)didReceiveMemoryWarning

    {

        [super didReceiveMemoryWarning];

        

        [queue cancelAllOperations]; // 取消队列中的所有任务(不可恢复)

    }

    // 开始滚动的时候暂停队列中的任务.

    - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView

    {

        [queue setSuspended:YES]; // 暂停队列中的所有任务

    }

    // 滚动结束的时候恢复队列中的任务.

    - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate

    {

        [queue setSuspended:NO]; // 恢复队列中的所有任务

    }


    2.线程间通信  // 子线程下载图片,主线程设置图片.

    

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    

    [queue addOperationWithBlock:^{

        // 1.异步下载图片

        NSURL *url = [NSURL URLWithString:@"http://d.hiphotos.baidu.com/image/pic/item/37d3d539b6003af3290eaf5d362ac65c1038b652.jpg"];

        NSData *data = [NSData dataWithContentsOfURL:url];

        UIImage *image = [UIImage imageWithData:data];

        

        // 2.回到主线程,显示图片

        [[NSOperationQueue mainQueue] addOperationWithBlock:^{

            self.imageView.image = image;

        }];

    }];

    

}

// 定义一个全局的队列属性.方便在任何方法中都可以使用这个Queue

@property (nonatomic,strong) NSOperationQueue *queue;


// UI 控件用 weak Strong 都没有问题.

// 在开发中,基本会见到所有的UI控件都是用 Strong来做的.

// UI控件一般不要用懒加载的方式加载.UI控件与用户是对应的.UI控件之外的,能用懒加载就用懒加载.

@property (nonatomic,strong) UIButton *button;


// 设置最大并发数.最多同时只能开启6条线程.

[_queue setMaxConcurrentOperationCount:6];

// 这里直接在Block 中使用 self 会造成循环引用. Block使用的注意点之一:循环引用.

//  __weak typeof(self) wself = self; wself 就是 self 的弱引用写法.


// GCD中的任务都是封装在Block,如果GCD中的Block中出现了 self,会造成循环引用吗?

//


//    dispatch_async(dispatch_get_main_queue(), ^{

//        [self test];

//    }); 会造成循环引用吗? 不会造成循环引用,因为 self 对这个Block 没有强引用.


// 创建操作

__weak typeof(self) wself = self;

NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{

    

    // Block中出现self .Block self 是强引用.

    [wself test];

}];


// 将操作添加到队列中.

// self.queue op 就是强引用.

[self.queue addOperation:op];



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值