认识和使用NSOperation

来源:互联网 发布:async await python 编辑:程序博客网 时间:2024/04/29 21:44

转自:http://www.jianshu.com/p/813f7d58935d


NSOperation是OC中多线程技术的一种,是对GCD的OC包装.它包含队列(NSOperationQueue)操作(NSOperation)两个基本要素.

通过这篇文章你可以了解到:

  • 怎样使用NSOperation
  • 怎样使用NSOperationQueue
  • 如何给NSOperationQueue设置并发数
  • NSOperationQueue的暂停恢复和取消
  • 通过添加依赖影响操作的执行顺序
  • NSOperation的进程间通信

怎样使用NSOperation

  • NSOperation本身是一个抽象类,要使用可以通过以下几个办法:
    • 使用NSInvocationOperation
    • 使用NSBlockOperation
    • 自定义NSOperation的子类

使用

  • NSInvocationOperation
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task) object:nil];// 调用start方法执行操作op操作[op start];
  • NSBlockOperation
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{    NSLog(@"task0---%@", [NSThread currentThread]);}];[op start];

根据打印的结果我们会发现,直接调用start方法时,系统并不会开辟一个新的线程去执行任务,任务会在当前线程同步执行.

注意: 这里我们说的是当前线程而非主线程,意即:如果是在主线程中调用op的start方法,那么该任务是在主线程中执行;但如果是在其他子线程调用start方法,任务则是在其他子线程执行.

当然NSBlockOperation还有一种使用方法addExecutionBlock:使得我们可以给其添加更多的操作,使用如下:

NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{    NSLog(@"task0---%@", [NSThread currentThread]);}];[op addExecutionBlock:^{    NSLog(@"task1----%@", [NSThread currentThread]);}];[op addExecutionBlock:^{    NSLog(@"task2----%@", [NSThread currentThread]);}];// 开始必须在添加其他操作之后[op start];

由打印的结果发现: task0的结果和前面的结论一样,是执行在主线程中的(因为是在主线程中调用start方法),但task1和task2都是在自己的新线程中执行.也就是说:当NSBlockOperation封装的操作数大于1的时候,就会执行异步操作.

  • 自定义NSOperation

自定义NSOperation的方法也很简单,我们需要做到下面几个步骤:
1.子类化NSOperation
2.在.m文件里面实现-(void)main方法
3.初始化该操作的时候直接调用alloc及init即可
4.同样可以通过start方法让你自定义的任务跑在当前线程中
关键代码:

自定义NSOperation的实现文件:

#import "AROperation.h"@implementation AROperation- (void)main {    NSLog(@"this is my custom operation ---- %@", [NSThread currentThread]);}@end

使用(在任何需要启用该任务的地方):

// 该操作被执行时就会执行op内部定义的任务AROperation *op = [[AROperation alloc] init];[op start];

怎样使用NSOperationQueue

NSOperation的start方法默认是同步执行任务,这样的使用并不多见,只有将NSOperation与NSOperationQueue进行结合,才会发挥出这种多线程技术的最大功效.当NSOperation被添加到NSOperationQueue中后,就会全自动地执行异步操作.

  • NSOperationQueue的种类:

    • 自带主队列[NSOperationQueue mainQueue]: 添加到主队列中的任务都会在主线程中执行
    • 自己创建队列(非主队列)
      NSOperationQueue *queue = [[NSOperationQueue alloc] init];: 这种队列同时包含串行、并发的功能,添加到非主队列的任务会自动放到子线程中执行
  • 向NSOperationQueue中添加操作:

    • 直接添加
      [queue addOperation:op1];
    • 使用block添加,block的内容会被包装成operation对象添加到队列
      [queue addOperationWithBlock:^{}];
      操作一但被到添加到队列中,就会自动异步执行.

设置NSOperationQueue的最大并发数

NSOperationQueue可以通过以下方法设置最大并发数,
setMaxConcurrentOperationCount:,值得注意的是:当并发数为1就变成了串行执行任务

NSOperationQueue的暂停恢复和取消

  • 取消
    • NSOperation有一个cancel方法可以取消单个操作
    • NSOperationQueue的cancelAllOperations相当于队列中的每个operation调用了cancel方法,会取消队列里面全部的操作.
    • 但是,不能取消正在进行中的任务,队列调用了cancelAllOperations后会等当前正在进行的任务执行完闭后取消后面的操作
  • 挂起和恢复
    • isSuspended : 判断是否挂起
    • setSuspended: YES表示挂起,NO表示恢复
    • 和取消功能类似,我们同样不能挂起正在运行中的操作,队列会等当前操作结束后将后面的操作暂停(挂起)

因此, 我们在自定义NSOperation的时候需要注意,最好可以经常通过判断isCancelled方法检测操作是否被取消,以响应外部可能进行的取消操作.如:

// 自定义NSOperation类.m文件的main方法实现- (void)main {    for (NSInteger i = 0; i < 1000; i++) {        NSLog(@"SubTask---0---%zd",i);    }    // 判断当前任务是否被取消,如果已经取消,及时返回    if (self.cancelled) {        return;    }    for (NSInteger i = 0; i < 1000; i++) {        NSLog(@"SubTask---1---%zd", i);    }    if (self.cancelled) {        return;    }    for (NSInteger i = 0; i < 1000; i++) {        NSLog(@"SubTask---2---%zd",i);    }}

添加依赖和监听

  • 通过设置操作间的依赖,可以确定这些操作的执行顺序
    如:
[op3 addDependency:op1];[op3 addDependency:op2];表示op3会在op1和op2都执行完毕后才执行

添加依赖的时候要注意防止添加循环依赖,此外我们还可以在不同队列的operation之间添加依赖

  • 监听
    • op.completeBlock可以监听一个操作执行完毕的时刻,这个block里面可以添加一些我们需要执行的操作
    • 这个block里面的操作仍然是在子线程执行,但不一定和被监听的操作在同一个线程

线程间通信

有时我们在子线程中执行完一些操作的时候,需要回到主线程做一些事情(如进行UI操作),因此需要从当前线程回到主线程,以下载并显示图片为例,方法如下:

NSOperationQueue *queue = [[NSOperationQueue alloc] init];// 子线程下载图片[queue addOperationWithBlock:^{    NSURL *url = [NSURL URLWithString:@"http://img.pconline.com.cn/images/photoblog/9/9/8/1/9981681/200910/11/1255259355826.jpg"];    NSData *data = [NSData dataWithContentsOfURL:url];    UIImage *image = [[UIImage alloc] initWithData:data];    // 回到主线程进行显示    [[NSOperationQueue mainQueue] addOperationWithBlock:^{        self.imageView.image = image;    }];}];

NSOperation的使用还是比较简单的,但是要注意的细节比较多,一些方法比较容易被忽略,于是乎特此总结一下.这里就不上传示例代码了,有问题的童鞋可以直接留言.


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 c1骑摩托车要拘留怎么办 欠钱的找不到人怎么办 治安拘留人跑了怎么办 行政拘留拘留所不收应该怎么办 在看守所被打了怎么办 取保候审超过12个月怎么办 拘留20天还没有判刑怎么办 被打了没有证据怎么办 拘留37天后没有放人怎么办 强制执行执行的财产不够怎么办 收到公安局拘留通知家属应该怎么办 对方不出谅解书怎么办 寻衅滋事没抓的 怎么办 公务员政审父母拘留过怎么办 我参与了网赌怎么办 亲人出车祸去世家属怎么办 车牌换了原保险怎么办 北京车牌夫妻变更车险怎么办 赌博拘留15天不交罚款怎么办 给人打了不赔钱怎么办 打了人对方讹钱怎么办 换车了原来的etc怎么办 换异地车牌了etc怎么办 被执行人拘留15天后不还钱怎么办 被执行人拘留后还是不还钱怎么办 摩托车套牌被交警扣了怎么办 套牌摩托车遇到交警怎么办 不知情收到小偷东西了怎么办 盗窃罪法院判定农民赔钱没钱怎么办 公安局通知家属取刑拘通知书怎么办 老公诈骗坐牢家人该怎么办 家人被拘留我该怎么办 车牌被偷了一个怎么办 车牌给人家偷了怎么办 收购了偷来的铝怎么办 员工自动离职后档案怎么办 辞职了老板不发工资怎么办 上班老板不发工资怎么办 逮捕后延长羁押期限怎么办手续 员工提出辞职公司不同意怎么办 员工提出辞职后即不来上班怎么办