NSOperation(多线程005)

来源:互联网 发布:淘宝开店找货源 编辑:程序博客网 时间:2024/05/18 06:18

1. NSOperation简介

优点

  • 是OC语言中基于GCD的面向对象的封装

  • 使用起来比GCD更加简单(面向对象)

  • 供了一些用GCD不好实现的功能

  • 苹果推荐使用,使用NSOperation不用关心线程以及线程的生命周期

特点

NSOperation是一个抽象类

  1. 不能直接使用(方法没有实现)
  2. 约束子类都具有共同的属性和方法

NSOperation的子类

  1. NSInvocationOperation
  2. NSBlockOperation
  3. 自定义operation

NSOperationQueue 队列

与GCD中的队列类似的概念

  • 并发队列
  • 异步执行

2. NSInvocationOperation使用方法

  • 执行操作
//创建操作NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadFile:) object:@"fileName"];//在当前线程执行方法(开始执行操作)[op start];

此方法不开线程

  • 把操作添加到队列(并开始异步执行)
//创建操作NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector: @selector(downloadFile:) object:@"fileName"];//将操作添加到队列,会自动异步调用方法NSOperationQueue *queue = [[NSOperationQueue alloc] init];[queue addOperation:op];- (void)downloadFile:(id)object{ NSLog(@"下载:%@----线程:%@",object,[NSThread currentThread]);}

开线程,异步执行

  • 添加多个操作到队列
- (void)opDemo3 {    NSOperationQueue *q = [[NSOperationQueue alloc] init];    for (int i = 0; i < 10; ++i) {        NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadImage:) object:@(i)];        [q addOperation:op];    }}}

开启多个线程,不会顺序执行---》GCD并发队列,异步执行

3. NSBlockOperation代码演示

  • NSBlockOperation
//队列NSOperationQueue *queue = [[NSOperationQueue alloc] init]; for (int i = 0; i < 10; i++) {//操作NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{NSLog(@"down %d %@",i,[NSThread currentThread]); }];[queue addOperation:op]; }
  • NSOperationQueue添加block的operation代码更简练
NSOperationQueue *queue = [[NSOperationQueue alloc] init];for (int i = 0; i < 10; i++) {[queue addOperationWithBlock:^{NSLog(@"down %d %@",i,[NSThread currentThread]); }];}
  • 全局操作队列(controller的全局),调度所有的异步操作 定义属性
@property (nonatomic, strong) NSOperationQueue *queue; 懒加载队列- (NSOperationQueue *)queue{if (_queue == nil) {_queue = [[NSOperationQueue alloc] init]; }return _queue; }for (int i = 0; i < 10; i++) {[self.queue addOperationWithBlock:^{NSLog(@"down %d %@",i,[NSThread currentThread]); }];}
  • 监听操作完成
[op1 setCompletionBlock:^{NSLog(@"....."); }];

4. 线程间通讯

- (void)opDemo6 {    NSOperationQueue *q = [[NSOperationQueue alloc] init];    [q addOperationWithBlock:^{        NSLog(@"耗时操作 %@", [NSThread currentThread]);        // 主线程更新 UI        [[NSOperationQueue mainQueue] addOperationWithBlock:^{            NSLog(@"更新 UI %@", [NSThread currentThread]);        }];    }];}

5. 其他特性以及用法

全局队列

/// 全局操作队列,统一管理所有的异步操作@property (nonatomic, strong) NSOperationQueue *queue;- (NSOperationQueue *)queue {    if (_queue == nil) {        _queue = [[NSOperationQueue alloc] init];    }    return _queue;}

此方式成为懒加载

最大并发数

/// MARK: - 最大并发操作数- (void)opDemo1 {    // 设置同时并发操作数    self.queue.maxConcurrentOperationCount = 2;    NSLog(@"start");    for (int i = 0; i < 10; ++i) {        NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{            [NSThread sleepForTimeInterval:1.0];            NSLog(@"%@ %d", [NSThread currentThread], i);        }];        [self.queue addOperation:op];    }}

GCD不能指定最大线程数

暂停 & 继续

/// MARK: - 暂停 & 继续- (IBAction)pauseAndResume {    if (self.queue.operationCount == 0) {        NSLog(@"没有操作");        return;    }    // 暂停或者继续    self.queue.suspended = !self.queue.isSuspended;    if (self.queue.isSuspended) {        NSLog(@"暂停 %tu", self.queue.operationCount);    } else {        NSLog(@"继续 %tu", self.queue.operationCount);    }}
  • 队列挂起,当前"没有完成的操作",是包含在队列的操作数中的
  • 队列挂起,不会影响已经执行操作的执行状态
  • 对列一旦被挂起,再添加的操作不会被调度

取消全部操作

/// MARK: - 取消所有操作- (IBAction)cancelAll {    if (self.queue.operationCount == 0) {        NSLog(@"没有操作");        return;    }    // 取消对列中的所有操作,同样不会影响到正在执行中的操作!    [self.queue cancelAllOperations];    NSLog(@"取消全部操作 %tu", self.queue.operationCount);}
  • 取消队列中所有的操作
  • 不会取消正在执行中的操作
  • 不会影响队列的挂起状态

依赖关系

/// MARK: - 依赖关系- (void)dependency {    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{        NSLog(@"登录 %@", [NSThread currentThread]);    }];    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{        NSLog(@"付费 %@", [NSThread currentThread]);    }];    NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{        NSLog(@"下载 %@", [NSThread currentThread]);    }];    NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{        NSLog(@"通知用户 %@", [NSThread currentThread]);    }];    [op2 addDependency:op1];    [op3 addDependency:op2];    [op4 addDependency:op3];    // 注意不要循环依赖//    [op1 addDependency:op4];    [self.queue addOperations:@[op1, op2, op3] waitUntilFinished:NO];    [[NSOperationQueue mainQueue] addOperation:op4];    NSLog(@"come here");}

用来控制任务之间执行的顺序

6. NSOperation与GCD的对比

GCD

  • 将任务(block)添加到队列(串行/并发/主队列),并且指定任务执行的函数(同步/异步)
  • GCD是底层的C语言构成的API
  • iOS 4.0 推出的,针对多核处理器的并发技术
  • 在队列中执行的是由 block 构成的任务,这是一个轻量级的数据结构
  • 要停止已经加入 queue 的 block 需要写复杂的代码
  • 需要通过 Barrier 或者同步任务设置任务之间的依赖关系
  • 只能设置队列的优先级
  • 高级功能: 一次性 once 延迟操作 after 调度组

NSOperation

  • 核心概念:把操作(异步)添加到队列(全局的并发队列)
  • OC 框架,更加面向对象,是对 GCD 的封装
  • iOS 2.0 推出的,苹果推出 GCD 之后,对 NSOperation 的底层全部重写
  • Operation作为一个对象,为我们提供了更多的选择
  • 可以随时取消已经设定要准备执行的任务,已经执行的除外
  • 可以跨队列设置操作的依赖关系
  • 可以设置队列中每一个操作的优先级
  • 高级功能: 最大操作并发数(GCD不好做) 继续/暂停/全部取消 跨队列设置操作的依赖关系



0 0