Operation与GCD的不同

最大并发数:

什么是并发数?

同时执行的任务数。比如同时开启三个线程执行三个任务,并发数就是3.

最大并发数相关的方法:

-(NSInteger)maxConcurrentOperationCount;

-(void)setMaxConcurrentOperationCount:(NSInteger)cnt;

剖析最大并发数:并发数就是同时执行操作的数量,并不是只线程的个数。就是指同时执行任务的个数,当一个线程执行完毕后会有一个回收到线程池的过程,这时如果线程池中还有别的线程就会直接拿出来进行任务的执行。如果线程池中没有线程,就会等待回收后的线程。

注:最大线程个数是由CPU内核决定的

GCD与NSOPeration的线程的不同之处

1。我们知道GCD的线程大体可分为六大中,同步串行队列(不开辟线程),同步并行队列(开辟线程),异步串行队列(开辟线程),异步并行队列(开辟线程),主队列, 全局队列。

    但是我们知道开辟线程和耗费内存,而GCD中方法虽多,但是很多我们开辟线程并没有意义,反而会耗费内存。NSOPeration其实是对GCD中的一个封装,但是他并没有封装GCD中所有的方法。NSOperationQueue创建出来的对象相当于异步并行队列,NSInvocationOperation如有start这相当于同步串行队列。NSBlockOperation将创建的对象加到NSOperationQueue创建队列中,相当一异步串行

 NSOperationQueue * q = [NSOperationQueue mainQueue]相当于GCD的主队列

 

2.队列的取消、暂停、和恢复NSOPeration有,GCD是没有的

取消队列的所有操作

-(void)cancelAllOperations;

提示:也可以调用NSOperation的-(void)cancel方法取消单个操作。

暂停和恢复队列

-(void)setSuspended:(BOOL)b; // YES表示暂停队列 NO表示恢复队列

-(BOOL)isSuspend;

获取队列操作数:

operationCount(只读属性)

注意:

(1)暂停不会删除队列内的操作。只是把队列挂起。暂停和挂起都是针对队列而言的。暂停后还可以重新恢复接着原来的任务进行执行。

(2)取消全部任务的操作会清空队列里的所有任务。

(3)暂停和取消都是对队列里的操作而言的,而正在执行的操作是无法取消或暂停的。

在实际的开发中:通常定义一个全局的操作队列, 然后就可以把所有的任务都添加进去。在开发中需要注意的两点:

(1)在用户点击”暂停/继续”的按钮触发的事件中,需要先判断当前队列内是否有任务,如果全局队列内没有任务就直接return返回,从而没有任务的时候不会改变队列的挂起和恢复状态。

(2)在用户点击”取消全部操作”的按钮触发的事件中,取消操作之后需要重置全局队列为恢复状态,这样不管原先全局队列的状态如何,在取消全部操作之后又重新置于初始状态。从而不会影响新的操作。

 代码

- (void) viewDidLoad
{
    self.view.backgroundColor = [UIColor whiteColor];
    
    UIButton * downButton = [UIButton buttonWithType:UIButtonTypeCustom];
    downButton.frame = CGRectMake(20, 80, 200, 60);
    [downButton setBackgroundColor:[UIColor greenColor]];
    [downButton addTarget:self action:@selector(download) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:downButton];
}

- (void) download
{
    if (self.opQueue.operationCount == 0) {
        NSLog(@"没有操作");
        return;
    }
    //暂停,继续
    self.opQueue.suspended = !self.opQueue.suspended;
    if (self.opQueue.suspended) {
        NSLog(@"暂停");
    }
    else
    {
        NSLog(@"继续");
    }

}
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//    [self opDemo1];
//    [self opDemo2];
//    [self opDemo3];
//    [self opDemo4];
    [self opDemo5];
}
//懒加载
- (NSOperationQueue *)opQueue
{
    if(_opQueue == nil)
    {
        _opQueue = [[NSOperationQueue alloc] init];
    }
    return _opQueue;
    
}

#pragma mark - 线程间通信
- (void) opDemo5
{ 
    self.opQueue = [[NSOperationQueue alloc] init];
//maxConcurrentOperationCount 必须要设,否者暂停不了
//个人理解,若不设置最大并发数,则所有任务并发执行,而暂停操作只能暂停还没开始的任务。下载中的任务不会暂停
//maxCincurrentOpertaionCount为多少,暂停下载后。就会有多少任务下载完成,因为点击暂停时,还有这么多人物在执行中 self.opQueue.maxConcurrentOperationCount
= 1; NSLog(@"+1"); for (int i = 0; i < 500; i ++) { NSOperation * op = [NSBlockOperation blockOperationWithBlock:^{ [NSThread sleepForTimeInterval:1]; NSLog(@"%d 耗时操作 ===== %@", i,[NSThread currentThread]); }]; [self.opQueue addOperation:op]; } NSLog(@"+3"); }

 NSOperation之间可以设置依赖来保证执行顺序,这是GCD所不具备的功能:

比如一定要让操作A执行完后,才能执行操作B,可以这么写:

[operationB addDependency:operationA];  // 操作B依赖于操作

 - 具体使用:将任务(block)添加到队列(串行/并发(全局)),指定执行任务的方法(同步(阻塞)/异步)

 - 线程通信:获取主线程dispatch_get_main_queue()。在主线程更新UI

 -  还有NSOperation无法做到的事:一次性执行,延迟执行,调度组(NSOperation相对复杂)

 NSOperation ---->ios2.0(后来改造了NSOperation的底层)

 - 具体使用:将操作(异步执行的)添加到队列(并发/全局)。其实就是封装了GCD里的异步执行全局或并发队列。

 - 线程通信: [[NSOperationQueue mainQueue] addOperation:op3];拿到主队列,往主队列添加操作(更新UI)

 - 提供了一些GCD无法实现的功能:最大并发数” 

 - 暂停/继续 -------挂起

 - 取消所有任务

 - 依赖关系

  1 <span style="font-size:18px;">//
  2 //  ViewController.m
  3 //  NSOperation之线程间通信
  4 //
  5 //  Created by apple on 15/10/22.
  6 //  Copyright (c) 2015年 LiuXun. All rights reserved.
  7 //
  8 
  9 #import "ViewController.h"
 10 
 11 @interface ViewController ()
 12 /**
 13  一般开发中,会定义一个全局的队列。整个程序都可以把操作往里面放。
 14  负责调度所有的操作
 15  */
 16 @property(nonatomic, strong) NSOperationQueue *opQueue;
 17 @end
 18 
 19 @implementation ViewController
 20 
 21 /**
 22  小结:
 23  只要是NSOperation的子类,就能添加到操作队列
 24  - 一旦操作添加到队列, 就会自动异步执行
 25  - 如果没有添加到队列, 而是使用start方法,就会在当前线程执行操作
 26  - 如果是线程间通信, 可以使用[NSOperaionQueue mainQueue] 拿到主队列,往主队列添加操作(更新UI)
 27  */
 28 
 29 /**
 30  GCD----> ios4.0
 31  - 具体使用:将任务(block)添加到队列 (串行/并发(全局)) ,指定执行任务的方法(同步(阻塞)/异步)
 32  - 线程通信:获取主线程dispatch_get_main_queue()。在主线程更新UI
 33  -  还有NSOperation无法做到的事:一次性执行,延迟执行,调度组(NSOperation相对复杂)
 34  
 35  NSOperation ---->ios2.0 (后来改造了NSOperation的底层)
 36  - 具体使用:将操作(异步执行的)添加到队列(并发/全局)。其实就是封装了GCD里的异步执行全局或并发队列。
 37  - 线程通信: [[NSOperationQueue mainQueue] addOperation:op3];拿到主队列,往主队列添加操作(更新UI)
 38  - 提供了一些GCD无法实现的功能:“最大并发数”
 39  - 暂停/继续 ------- 挂起
 40  - 取消所有任务
 41  - 依赖关系
 42  */
 43 
 44 /**
 45  懒加载的方式,初始化NSOperationQueue对象
 46  */
 47 -(NSOperationQueue *)opQueue
 48 {
 49     if(_opQueue == nil)
 50     {
 51         _opQueue = [[NSOperationQueue alloc] init];
 52     }
 53     return _opQueue;
 54 }
 55 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
 56 {
 57     [self dependcy];
 58 }
 59 #pragma mark - 线程间通信(非常重要)
 60 -(void)opDemo1
 61 {
 62     NSOperationQueue *q = [[NSOperationQueue alloc] init];
 63     [q addOperationWithBlock:^{
 64         NSLog(@"耗时操作......%@", [NSThread currentThread]);
 65         
 66         // 在主线程更新UI
 67         [[NSOperationQueue mainQueue] addOperationWithBlock:^{
 68             NSLog(@"更新UI......%@", [NSThread currentThread]);
 69         }];
 70     }];
 71 }
 72 
 73 #pragma mark- 最大并发数
 74 /**
 75  注意:最大并发数不是说线程的数量,而是说同时进行操作的数量
 76  */
 77 -(void)opDemo2
 78 {
 79     self.opQueue.maxConcurrentOperationCount = 2;
 80     for(int i=0; i<10 ; i++){
 81         NSOperation *op = [NSBlockOperation blockOperationWithBlock:^{
 82             [NSThread sleepForTimeInterval:1.0];
 83             NSLog(@"%@------%d", [NSThread currentThread], i);
 84         }];
 85         [self.opQueue addOperation:op];
 86     }
 87 }
 88 
 89 #pragma mark - 高级操作  挂起
 90 // 就是暂停和继续:  对队列的操作
 91 /**
 92  应用场景:比如当我们在有WiFi的地发用手机下载电影,但是有事情走开了,断网了电影只下载了一半,这时就需要挂起,等到了有网的地方又可以接着原来的进度下载。
 93  切记:挂起的是队列,不会影响已经在执行的操作
 94  */
 95 -(IBAction)pause
 96 {
 97     
 98     // 判断操作的数量,当前队列里面是否有操作
 99     if(self.opQueue.operationCount == 0){
100         NSLog(@"没有操作");
101         return; // 没有操作的时候直接return,不会修改队列的状态
102     }
103     
104     // 暂停继续 :
105     self.opQueue.suspended = !self.opQueue.suspended;
106     if(self.opQueue.suspended){
107         NSLog(@"暂停");
108     }else
109     {
110         NSLog(@"继续");
111     }
112 }
113 
114 #pragma mark- 高级操作 队列取消
115 /**
116  取消操作并不会影响队列的挂起状态
117  */
118 -(IBAction)cancel
119 {
120     // 取消队列内的所有操作
121     // 只是取消队列里的任务,而正在执行的任务是无法取消的
122     // 另外取消了任务就是删除了队列内的所有操作
123     [self.opQueue cancelAllOperations];
124     NSLog(@"取消所有操作");
125     
126     // 取消队列的挂起状态(只要是取消了队列的操作,我们就把队列处于一个启动状态,以便于后续的开始)
127     self.opQueue.suspended = NO;
128 }
129 
130 #pragma mark -依赖关系
131 -(void)dependcy
132 {
133     /**
134      举例场景:
135      1. 下载一个小说的压缩包
136      2. 解压缩,删除压缩包
137      3. 更新UI
138      */
139     NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
140         NSLog(@"下载一个小说的压缩包,%@",[NSThread currentThread]);
141     }];
142     NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
143         NSLog(@"解压缩,删除压缩包,%@",[NSThread currentThread]);
144     }];
145     NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
146         NSLog(@"更新UI,%@",[NSThread currentThread]);
147     }];
148     // 如果直接把任务添加到队里,会异步执行,使顺序错乱
149     
150     // 因此需要指定任务之间的依赖关系--------依赖关系可以跨队列(可以在子线程下载完,到主线程更新UI)
151     [op2 addDependency:op1];  // op2 依赖于op1  就是执行op2之前必须先执行op1
152     [op3 addDependency:op2];  // op3 依赖于op2  就是执行op3之前必须先执行op2
153     
154     /**
155      千万注意:不要造成相互依赖即依赖循环,会造成死锁
156      */
157     //    [op1 addDependency:op3];
158     
159     
160     // waitUntilFinished 类似于GCD中调度组的通知
161     // NO表示不等待当前的队列执行完毕,就执行下面的代码,打印 NSLog(@"任务完成");
162     // YES 表示必须等队列内的任务全部执行完毕才执行下面的代码
163     [ self.opQueue addOperations:@[op1, op2] waitUntilFinished:YES];
164     
165     // 在主线程更新UI
166     [[NSOperationQueue mainQueue] addOperation:op3];
167     
168     NSLog(@"任务完成");
169 }
170 @end
171 </span>

 

 

 

 

转载于:https://www.cnblogs.com/YU411524/p/4925120.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值