必威-必威-欢迎您

必威,必威官网企业自成立以来,以策略先行,经营致胜,管理为本的商,业推广理念,一步一个脚印发展成为同类企业中经营范围最广,在行业内颇具影响力的企业。

设置最大并发数必威,使用它的子类的方法有三

2019-09-16 00:01 来源:未知

NSOperation介绍

  • NSOperation

    1. 是 OC 语言中基于 GCD 的面向对象的封装。
    2. 使用起来比GCD更加简单。
    3. 提供了一些用GCD不好实现的功能。
    4. 苹果推荐使用,使用NSOperation不用关心线程以及线程的生命周期。
  • NSOperation的使用

    1. 使用NSOperation处理多线程时,就是将“操作”添加到队列中。
    2. NSOperation是一个抽象类,不能直接使用,约束子类都具有共同的属性和方法。
    3. NSOperation的子类:NSInvocationOperationNSBlockOperation自定义NSOperation
    4. 通过NSOperationQueue可以创建并发队列,获取主队列,获取当前队列。

必威 1NSInvocationOperation的使用必威 2NSBlockOperation的使用必威 3监听操作完成,回调函数

  • 线程间通讯
    • 主队列,添加到主队列的操作,最终都执行在主线程上。通过NSOperationQueue的mainQueue获取主队列。
    • 通过NSOperationQueue的currentQueue获取当前操作所在的队列。

必威 4线程间通讯

  • GCD和NSOperation的对比
    1. GCD
      • GCD是iOS4.0推出的,主要针对多核CPU做了优化,是C语言的技术。
      • GCD是将任务添加到队列(串行/并行/全局/主队列),并且以同步/异步的方式执行任务的函数。
      • GCD提供给了一些NSOperation不具备的功能:①一次性执行;②延迟执行;③调度组。
    2. NSOperation
      • NSOperation是iOS2.0推出的,iOS4.0之后重写了NSOperation。
      • NSOperation将操作添加到队列,就会执行指定操作的函数。
      • NSOperation里提供的方便的操作:①最大并发数;②队列的暂停/继续;③取消所有的操作;④指定操作之间的依赖关系(GCD可以用同步实现)。

NSOperation简介

  • 是OC语言中基于GCD的面向对象的封装
  • 使用起俩比GCD更加简单
  • 提供了一些用GCD不好实现的功能
  • 苹果推荐使用,使用NSOperation不用关心线程以及线程的生命周期问题
  • NSOperation是一个抽象类,不能直接使用(方法没有实现)
  • 约束子类都有共同的属性和方法
  • NSOperation的子类

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

  • NSOperationQueue队列

本文导读:NSOperation作为苹果推荐的重要并发技术之一,在开发当中也较为常用。本文将详细介绍NSOperation两个子类以及NSOperationQueue的使用。而笔者前面的文章[iOS多线程基础][1]已经详细介绍了简单的多线程NSThread和基于C语言的功能强大的GCD,有需要的同学可以去看一下。既然有三种多线程技术,那它们又有什么区别呢?使用场景怎样呢?笔者将在本文末尾为大家一一解答

1.NSOperation的作用

 

NSOperation中的方便的使用

  • 最大并发数
    1. 不设置队列的最大并发数:循环把操作添加到队列中,会创建很多线程,线程数越多说明线程池更大了。线程数多并不一定是好事儿,线程越多越耗资源,分配线程的时间也就越多,所以使用线程的时候要合适最好。
    2. 设置队列的最大并发数:循环把操作添加到队列中,会先去线程池中去取空闲的线程,如果没有就创建线程,然后把操作交给从线程池中取出的线程执行,执行完成后,把线程再放回线程池中,重复前面的步骤直到所有的操作都执行完。

必威 5设置最大并发数

  • 暂停/继续/取消/等待
    1. 暂停:设置暂停后,会等待正在执行的任务执行完成后,暂停后续的任务,继续就是对暂停取反。
    2. 取消:清除队列中的任务,取消所有操作,会设置当前队列中所有的操作的cancelled属性为YES,会立即取消所有操作,但是不会立即清空所有操作,而是过一会儿才清空所有操作。
    3. 等待:等待队列中的操作都执行完毕,会阻塞。
// 暂停@property (getter=isSuspended) BOOL suspended;// 取消- cancelAllOperations;// 等待- waitUntilAllOperationsAreFinished;
  • 依赖关系
    1. 两个操作之间的顺序叫做依赖关系
    2. 用这个方法addDependency:设置操作之间的依赖关系,然后把操作添加到队列中,此时因为设置好了依赖关系,添加顺序就可以随意。
    3. 依赖关系可以跨操作队列,操作不再同一个队列中,依赖关系也是存在的。

必威 6依赖关系

使用步骤

NSOperation和 NSOperationQueue是实现多线程的具体步骤:
1.先将需要执行的操作封装到一个NSOperation对象汇总
2.将NSOperation对象添加到NSOperationQueue中
系统会自动将NSOperationQueue中的NSOperation取出来
将去出来的NSOperation封装的操作放在一条新线程中执行
PS:队列先进先出

NSOperation是苹果推荐使用的并发技术,它提供了一些用GCD不是很好实现的功能。NSOperation是基于GCD的面向对象的使用OC语言的封装。相比GCD,NSOperation的使用更加简单。NSOperation是一个抽象类,也就是说它并不能直接使用,而是应该使用它的子类。使用它的子类的方法有三种,使用苹果为我们提供的两个子类 NSInvocationOperation,NSBlockOperation和自定义继承自NSOperation的子类。

配合使用NSOperation和NSOperationQueue也能实现多线程编程。

NSInvocationOperation

NSInvocationOperation

NSOperation的使用常常是配合NSOperationQueue来进行的。只要是使用NSOperation的子类创建的实例就能添加到NSOperationQueue操作队列之中,一旦添加到队列,操作就会自动异步执行(注意是异步)。如果没有添加到队列,而是使用start方法,则会在当前线程执行。

 

 

NSBlockOperation

我们知道,线程间的通信主要是主线程与分线程之间进行的。主线程到分线程,NSOperation子类也有相应带参数的方法;而分线程到主线程,比如更新UI,它也有很方便的获取主队列(被添加到主队列的操作默认会在主线程执行)的方法:[NSOperationQueue mainQueue]。

2.NSOperation和NSOperationQueue实现多线程的具体步骤:

// 基于一个对象和selector来创建操作。如果你已经有现有的方法来执行需要的任务,就可以使用这个类

自定义operation


一、NSInvocationOperation

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

   
    NSInvocationOperation * op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downImage) object:nil];
   
    // 如果我们想在一个NSOperation执行完毕后做一些事情,就调用NSOperation的setCompletionBlock方法来设置想做的事情
    [op setCompletionBlock:^{
        NSLog(@"完成");
    }];
   
    //    2.开始执行任务(同步执行)
   
    // 一个NSOperation对象可以通过调用start方法来执行任务,默认是同步执行的。

NSOperationQueue

1.NSOperationQueue的作用:NSOperation可以调用start方法来执行任务,但默认是同步执行.如果将NSOperation添加到NSOperationQueue(操作队列)中,系统会自动异步执行NSOperation中的操作.

2.添加到NSOperationQueue中
- (void)addOperation:(NSOperation *)op;
- (void)addOperationWithBlock:(void (^)(void))block NS_AVAILABLE(10_6, 4_0);

- (void)addOperations:(NSArray<NSOperation *> *)ops waitUntilFinished:(BOOL)wait NS_AVAILABLE(10_6, 4_0);

1.单个NSInvocationOperation

<1>直接创建一个NSInvocationOperation的对象,然后调用start方法会直接在主线程执行

//1.创建
  NSOperation *op = [[NSInvocationOperation alloc]initWithTarget:self 
selector:@selector(downloadImage:) object:@"Invocation"];
 //2.start方法,直接在当前线程执行
    [op start];

#pragma mark - 调用的耗时操作,后面调用的耗时操作都是这个
- (void)downloadImage:(id)obj{
  NSLog(@"%@-----%@",[NSThread currentThread],obj);
}

输出 [1151:50868] <NSThread: 0x7fae624047b0>{number = 1, name = main}-----Invocation

<2>添加到NSOperationQueue

 //1.创建
  NSOperation *op = [[NSInvocationOperation alloc]initWithTarget:self 
selector:@selector(downloadImage:) object:@"Invocation"];
 //2.放到队列里面去
    NSOperationQueue *q = [[NSOperationQueue alloc]init];
  //只要把操作放到队列,会自动异步执行调度方法
    [q addOperation:op];

输出:[1192:55469] <NSThread: 0x7fbe59e45c30>{number = 3, name = (null)}-----Invocation

在number为3,name为空的子线程执行

2.多个NSInvocationOperation

    //队列,GCD里面的并发队列使用最多,所以NSOperation技术直接把GCD里面的并发队列封装起来
  //NSOperationQueue本质就是GCD里面的并发队列
  //操作就是GCD里面异步执行的任务
  NSOperationQueue *q = [[NSOperationQueue alloc]init];

  //把多个操作放到队列里面
  for (int i = 0; i < 100; i++) {
    NSOperation *op = [[NSInvocationOperation alloc]initWithTarget:self 
         selector:@selector(downloadImage:) object:[NSString stringWithFormat:@"Invocation%d",i]];
    [q addOperation:op];
  }

输出:
**[1222:58476] <NSThread: 0x7fdc14b0cd20>{number = 7, name = (null)}-----Invocation5
**[1222:58478] <NSThread: 0x7fdc1357e5f0>{number = 9, name = (null)}-----Invocation7
**[1222:58307] <NSThread: 0x7fdc14a06ad0>{number = 3, name = (null)}-----Invocation1
**[1222:58477] <NSThread: 0x7fdc134916e0>{number = 8, name = (null)}-----Invocation6
**[1222:58481] <NSThread: 0x7fdc1357e120>{number = 12, name = (null)}-----Invocation10
**[1222:58475] <NSThread: 0x7fdc14801710>{number = 6, name = (null)}-----Invocation4
**[1222:58480] <NSThread: 0x7fdc13415630>{number = 11, name = (null)}-----Invocation9
**[1222:58306] <NSThread: 0x7fdc13512e20>{number = 4, name = (null)}-----Invocation3
··· ···

线程名与输出均没有规律,很明显就是并发队列。

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

    [op start];

线程间通讯

1.主队列

  • 添加到主队列的操作,最终都执行在主线程
  • [NSOperationQueue currentQueue];
    2.当前队列
  • 获取当前操作所在的队列
    [NSOperationQueue mainQueue];

二、NSBlockOperation

NSBlockOperation的用法与NSInvocationOperation相同,只是创建的方式不同,它不需要去调用方法,而是直接使用代码块,显得更方便。这也使得NSBlockOperation比NSInvocationOperation更加流行

    //跟GCD中的并发队列一样
  NSOperationQueue *q = [[NSOperationQueue alloc]init];
  //跟GCD中的主队列一样
//  NSOperationQueue *q = [NSOperationQueue mainQueue];
  //把多个操作放到队列里面
  for (int i = 0; i < 100; i++) {
    NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
      NSLog(@"%@------%d",[NSThread currentThread],i);

   }];
    //把Block操作放到队列
    [q addOperation:op];
  }
  NSLog(@"完成");

并发队列输出结果:
**[1378:72440] <NSThread: 0x7f9cb2603460>{number = 6, name = (null)}------5**
**[1378:72442] <NSThread: 0x7f9cb48106a0>{number = 5, name = (null)}------7**
**[1378:72441] <NSThread: 0x7f9cb242b3e0>{number = 7, name = (null)}------6**
**[1378:72325] <NSThread: 0x7f9cb4851550>{number = 9, name = (null)}------2**
**[1378:72320] <NSThread: 0x7f9cb492be70>{number = 4, name = (null)}------3**
**[1378:72313] <NSThread: 0x7f9cb24077b0>{number = 2, name = (null)}------1**
**[1378:72276] 完成
**[1378:72444] <NSThread: 0x7f9cb481cc40>{number = 11, name = (null)}------9**
**[1378:72326] <NSThread: 0x7f9cb4923fe0>{number = 3, name = (null)}------0**
**[1378:72440] <NSThread: 0x7f9cb2603460>{number = 6, name = (null)}------12**
... ...

主队列输出结果:
**[1417:76086] 完成
**[1417:76086] <NSThread: 0x7fa452e04360>{number = 1, name = main}------0**
**[1417:76086] <NSThread: 0x7fa452e04360>{number = 1, name = main}------1**
**[1417:76086] <NSThread: 0x7fa452e04360>{number = 1, name = main}------2**
**[1417:76086] <NSThread: 0x7fa452e04360>{number = 1, name = main}------3**
**[1417:76086] <NSThread: 0x7fa452e04360>{number = 1, name = main}------4**
**[1417:76086] <NSThread: 0x7fa452e04360>{number = 1, name = main}------5**
**[1417:76086] <NSThread: 0x7fa452e04360>{number = 1, name = main}------6**
**[1417:76086] <NSThread: 0x7fa452e04360>{number = 1, name = main}------7**
... ...

事实上NSBlockOperation有更简单的使用方法

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

  for (int i = 0; i < 10; i++) {

    [q addOperationWithBlock:^{
      NSLog(@"%@------%d",[NSThread currentThread],i);
    }];
  }

3)系统会自动将NSOperationQueue中的NSOperation取出来。

 

GCD VS NSOperation

  • GCD是iOS4推出的,主要针对多核CPU做了优化,C语言技术
  • GCD是将任务(block)添加到队列中(串行/并行/全局/主队列),并且以同步/异步的方式执行任务的函数
  • GCD提供了一些NSOperation不具备的功能
    • 一次性执行
    • 延时执行
    • 调度组
  • NSOperation
  • NSOperation是iOS2.0推出的,iOS4之后重写了NSOperation
  • NSOperation是将操作(异步的任务)添加到队列(并发队列),就会执行指定的操作函数
  • NSOperation提供方便操作
    • 最大并发数
    • 队列中的暂停/继续
    • 取消所有的操作
    • 指定操作之间的依赖关系(GCD中可以用同步实现)

队列的最大并发数:

  • 同时执行的任务数量,比如同时开3个线程执行3个任务,并发数就是3
  • 相关方法:@property NSInteger maxConcurrentOperationCount;
    例子
    NSOperationQueue *queue = [[NSOperationQueue alloc]init]; [queue setMaxConcurrentOperationCount:8]; queue.maxConcurrentOperationCount = 8;

队列的暂停/取消/恢复:

  • 取消队列的所有操作:
    - (void)cancelAllOperations;
  • 暂停和恢复队列的操作
    @property (getter=isSuspended) BOOL suspended;
    YES代表队列暂停,NO代表恢复队列
    暂停是当前正在执行的操作会继续执行下去,暂停后续的操作,取消原理也是如此.

优先级与服务质量

  • 设置NSOperation在queue中的优先级,可以改变操作的执行优先级
    typedef NS_ENUM(NSInteger, NSOperationQueuePriority) { NSOperationQueuePriorityVeryLow = -8L, NSOperationQueuePriorityLow = -4L, NSOperationQueuePriorityNormal = 0, NSOperationQueuePriorityHigh = 4, NSOperationQueuePriorityVeryHigh = 8 }; @property NSOperationQueuePriority queuePriority;
  • iOS8以后推荐使用qualityOfService

三、线程间通信

主线程到子线程传对象,前面的例子里面已经有了,不再缀述。下面的例子就是回到主线程更新UI。

p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Menlo; c

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

  [q addOperationWithBlock:^{
    NSLog(@"耗时操作--%@",[NSThread currentThread]);
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
      NSLog(@"更新UI-----%@",[NSThread currentThread]);
    }];
  }];

4)将取出来的NSOperation封装的操作放到一条新线程中执行。

 NSBlockOperation

四、NSOperationQueue的一些高级操作

NSOperationQueue支持的高级操作有:队列的挂起,队列的取消,添加操作的依赖关系和设置最大并发数

<1>最大并发数

@property (nonatomic,strong)NSOperationQueue *opQueue;

//重写getter方法实现懒加载
- (NSOperationQueue*)opQueue{
  if (_opQueue == nil) {
    _opQueue = [[NSOperationQueue alloc]init]; 
  }
  return _opQueue;
}


#pragma mark - 高级操作:最大并发数

  //设置最大的并发数量(并非线程的数量)
  self.opQueue.maxConcurrentOperationCount = 2;
  //把多个操作放到队列里面
  for (int i = 0; i < 10; i++) {
    NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
      [NSThread sleepForTimeInterval:3.0];
      NSLog(@"%@------%d",[NSThread currentThread],i);

    }];
    //把Block操作放到队列
    [self.opQueue addOperation:op];
  }

<2>线程的挂起

#pragma mark - 高级操作:线程的挂起
//暂停继续(对队列的暂停和继续),挂起的是队列,不会影响已经在执行的操作
- (IBAction)pause:(UIButton *)sender {
  //判断操作的数量,当前队列里面是不是有操作?
  if (self.opQueue.operationCount == 0) {
    NSLog(@"当前队列没有操作");
    return;
  }

  self.opQueue.suspended = !self.opQueue.isSuspended;
  if (self.opQueue.suspended) {
    NSLog(@"暂停");

  }else{
    NSLog(@"继续");
  }
}

<3>取消队列里的所有操作

#pragma mark - 高级操作:取消队列里的所有操作
- (IBAction)cancelAll:(UIButton *)sender {
  //只能取消所有队列的里面的操作,正在执行的无法取消
  //取消操作并不会影响队列的挂起状态
  [self.opQueue cancelAllOperations];
  NSLog(@"取消队列里所有的操作");
  //取消队列的挂起状态
  //(只要是取消了队列的操作,我们就把队列处于不挂起状态,以便于后续的开始)
  self.opQueue.suspended = NO;

}

<4>依赖关系

    /*
  * 例子
  *
  * 1.下载一个小说压缩包
  *  2.解压缩,删除压缩包
  * 3.更新UI
  */

  NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"1.下载一个小说压缩包,%@",[NSThread currentThread]);

  }];

  NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"2.解压缩,删除压缩包,%@",[NSThread currentThread]);

  }];

  NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"3.更新UI,%@",[NSThread currentThread]);

  }];

  //指定任务之间的依赖关系 --依赖关系可以跨队列(可以再子线程下载,在主线程更新UI)

  [op2 addDependency:op1];
  [op3 addDependency:op2];
//  [op1 addDependency:op3];  一定不能出现循环依赖

  //waitUntilFinished  类似GCD中的调度组的通知
  //NO不等待,直接执行输出come here
  //YES等待任务执行完再执行输出come here
  [self.opQueue addOperations:@[op1,op2] waitUntilFinished:YES];


  //在主线程更新UI
  [[NSOperationQueue mainQueue] addOperation:op3];
  [op3 addDependency:op2];
  NSLog(@"come here");

还有一个NSOperationQueuePriority,队列优先级的概念,因为用的极少,所以这里不做介绍,确实有需要的同学可以自己百度或者查看Documentation and API Reference。

 

 

五、三种多线程技术

<1>NSThread

  • 优点:NSThread 比其他两个轻量级,使用简单
  • 缺点:需要自己管理线程的生命周期、线程同步、加锁、睡眠以及唤醒等。线程同步对数据的加锁会有一定的系统开销

<2>GCD
GCD 是iOS 4.0以后才出现的并发技术

  • 使用方式:将任务添加到队列(串行/并行(全局)),指定执行任务的方法,(同步(阻塞)/异步 )
  • 拿到主队列:dispatch_get_main_queu()
  • NSOperation无法做到的:1.一次性执行,2.延迟执行,3.调度组(op实现要复杂的多 )

<3>NSOperation
NSOperation iOS2.0的时候就出现了(当时不好用,后来苹果对其进行改造)

  • 使用方式:将操作(异步执行)添加到队列(并发/全局)
  • 拿到主队列:[NSOperationQueue mainQueue] 主队列,任务添加到主队列就会在主线程执行
  • 提供了GCD不好实现的:1.最大并发数,2.暂停和继续,3.取消所有任务,4.依赖关系

GCD是比较底层的封装,我们知道较低层的代码一般性能都是比较高的,相对于NSOperationQueue。所以追求性能,而功能够用的话就可以考虑使用GCD。如果异步操作的过程需要更多的用户交互和被UI显示出来,NSOperationQueue会是一个好选择。如果任务之间没有什么依赖关系,而是需要更高的并发能力,GCD则更有优势。
高德纳的教诲:“在大概97%的时间里,我们应该忘记微小的性能提升。过早优化是万恶之源。”只有Instruments显示有真正的性能提升时才有必要用低级的GCD。
[1]:http://www.jianshu.com/p/7267206834fb

3.NSOperation的子类

 //  能够并发地执行一个或多个block对象,所有相关的block都执行完之后,操作才算完成
    NSBlockOperation * op = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"%@",[NSThread currentThread]);
        
        NSLog(@"第一个操作");
    }];
    
    // 通过addExecutionBlock方法添加block操作,开启多个线程,三个线程
    [op addExecutionBlock:^{
        
        NSLog(@"%@",[NSThread currentThread]);
        
        NSLog(@"第二个操作");
    }];
    
    [op addExecutionBlock:^{
        
        NSLog(@"%@",[NSThread currentThread]);
        
        NSLog(@"第三个操作");
    }];
    
    [op start];

NSOperation是个抽象类,并不具备封装操作的能力,必须使用它的子类。

 

使用NSOperation子类的方式有3种:

NSOperationQueue-   一个操作序列

1) NSInvocationOperation

 

2) NSBlockOperation

//NSOperation是基于GCD的,把GCD的block封装成opertion,NSOperationQueue是全局队列封装
    //将NSOperation添加到一个NSOperationQueue(操作队列)中去执行,而且是异步执行的。
   
    //创建一个操作队列
    NSOperationQueue * queue = [[NSOperationQueue alloc] init];
   
    NSInvocationOperation * op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downImage) object:nil];
   
    NSBlockOperation * op2 = [NSBlockOperation blockOperationWithBlock:^{
       
        NSLog(@"op2 - %@",[NSThread currentThread]);
    }];
   
    //添加NSOperation到NSOperationQueue中
    //NSOperation添加到queue之后,通常短时间内就会得到运行。
    //    [queue addOperation:op];
    //    [queue addOperation:op2];
   
    //    waitUntilFinished yes 操作完成后执行下面的代码 no 先执行下面的代码
   
    //添加一个block形式的operation
    [queue addOperationWithBlock:^{
       
        NSLog(@"op3 - %@",[NSThread currentThread]);
       
    }];
   
    [queue addOperations:@[op,op2] waitUntilFinished:NO];     

3) 自定义子类继承NSOperation,实现内部相应的方法。

    //最大并发数,这个功能NSOperation比较常用
   
    queue.maxConcurrentOperationCount = 2;
   
    for (NSInteger i = 0; i < 10; i++) {
       
        NSInvocationOperation * op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downImage) object:nil];
       
        [queue addOperation:op];
    }  

 

NSOperationQueue的依赖关系

4.基本使用代码示例

 

/* NSInvocationOperation使用*/

 self.queue = [[NSOperationQueue alloc] init];
    
    NSInvocationOperation * op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downImage) object:nil];
    //设置优先级,数据量少看不出
    op1.queuePriority = -4;

-(void)downloadImage:(id)obj

    
    NSBlockOperation * op2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"解压图片包");
    }];
    op2.queuePriority = 0;

{

    
    NSBlockOperation * op3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"观看漫画");
    }];
    op3.queuePriority = 4;
    
    //添加NSOperation的依赖对象
//    [op2 addDependency:op1];
//    [op3 addDependency:op2];
    
    //注意:不能创建环形依赖,如A依赖B,B依赖A,这是错误的
    //    [op1 addDependency:op3];
    
    [self.queue addOperations:@[op1,op2,op3] waitUntilFinished:YES];

       NSLog(@”%@”, obj);

     //挂起状态
    self.queue.suspended = !self.queue.suspended;
// 不过暂停一个queue不会导致正在执行的operation在任务中途暂停,只是简单地阻止调度新Operation执行。

}

 

//创建操作

// 取消queue中所有的操作
    [self.queue cancelAllOperations];

NSOperation*op = [[NSInvocationOperation  alloc]initWithTarget:self selector:@selector(downloadImage:) object:@”Invocation”];

 

//启动,直接在当前线程执行

 //NSOperation 线程之间的通信

[opstart];

    [self.queue addOperationWithBlock:^{
       
        NSLog(@"%@",[NSThread currentThread]);
        NSLog(@"下载图片");
       
        //获取主队列
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
           
            NSLog(@"%@",[NSThread currentThread]);
            NSLog(@"更新UI");
           
        }];
    }];  

/*放到队列(GCD里面的并发队列(全局)队列使用最多。所以,NSOperationQueue技术直接把GCD里面的并发队列封装起来)。

NSOperation与GCD的区别

NSOperationQueue队列,本质就是GCD里面的并发队列。*/

/**
 *  GCD -- (iOS4.0)多线程解决方案
    将任务(block)添加到队列(串行,并行(全局队列)),指定执行任务的方法。(同步,异步)
    拿到dispatch_get_main_queue,线程之间的通信

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

 
    NSOperation -- (iOS2.0)  (后经苹果改造)
 
    将操作添加到队列里
    [NSOperationQueue mainQueue]  获取主队列,将任务添加到主队列,就会在主线程中执行
    NSOperation可以设置最大并发数(用GCD处理,比较麻烦)
    可以暂停可以继续,也就是挂起操作
    取消所有的任务
    设置依赖关系
 */  

//只要把操作添加到队列,会自动异步执行调度方法

[queueaddOperation:op];

 

/*NSBlockOperation 使用*/

//相当于GCD的并发队列

TAG标签:
版权声明:本文由必威发布于必威-编程,转载请注明出处:设置最大并发数必威,使用它的子类的方法有三