iOS多线程_08_NSOperation补充

四、最大并发数

  最大并发数是NSOperation特有的

1、什么是并发数

  同时执行的任务数

  比如,同时开3个线程执行3个任务,并发数就是3

2、最大并发数的相关方法

  - (NSInteger)maxConcurrentOperationCount;

  - (void)setMaxConcurrentOperationCount:(NSInteger)cnt;

(1)设置队列的最大并发(操作)数

    // 设置队列的最大并发数,队列是负责调度操作的
    self.queue.maxConcurrentOperationCount = 2;
    
    for (int i = 0; i < 10; i++) {
        [self.queue addOperationWithBlock:^{
            // 模拟休眠
            [NSThread sleepForTimeInterval:1.0f];
            
            NSLog(@"正在下载 %@ %d", [NSThread currentThread], i);
        }];
    }

  输出结果:

    正在下载 <NSThread: 0x8e2a260>{name = (null), num = 3} 0

    正在下载 <NSThread: 0x8d1f920>{name = (null), num = 2} 1

    正在下载 <NSThread: 0x8d1f920>{name = (null), num = 2} 3

    正在下载 <NSThread: 0x8e2a260>{name = (null), num = 3} 2

    正在下载 <NSThread: 0x8e2a260>{name = (null), num = 3} 5

    正在下载 <NSThread: 0x8d1f920>{name = (null), num = 2} 4

    正在下载 <NSThread: 0x8e2a260>{name = (null), num = 3} 6

    正在下载 <NSThread: 0x8d1f920>{name = (null), num = 2} 7

    正在下载 <NSThread: 0x8d1f920>{name = (null), num = 2} 9

    正在下载 <NSThread: 0x8e2a260>{name = (null), num = 3} 8

  结果说明,开启了2条子线程,每次调用2条线程执行任务。

  maxConcurrentOperationCount 如果== 3,结果是:

  最大并发数是3,实际运行过程中,使用到4条线程,每次调用3条线程执行任务。

  所以,最大并发数每次最多调用子线程的数量。具体在哪条线程上工作,是由系统分配的。

  maxConcurrentOperationCount 如果== 1,结果是:

 

  结果说明,如果 最大并发数 == 1类似于串行队列异步方法

(2)执行块中设置最大并发数

    // 实例化block操作
    NSBlockOperation *op = [[NSBlockOperation alloc] init];
    
    // 添加执行块
    [op addExecutionBlock:^{
        NSLog(@"下载书籍1 %@", [NSThread currentThread]);
    }];
    
    // 继续添加块
    [op addExecutionBlock:^{
        NSLog(@"下载书籍2 %@", [NSThread currentThread]);
    }];
    
    // 继续添加块
    [op addExecutionBlock:^{
        NSLog(@"下载书籍3 %@", [NSThread currentThread]);
    }];
    
    // 继续添加块
    [op addExecutionBlock:^{
        NSLog(@"下载书籍4 %@", [NSThread currentThread]);
    }];
    
    // 继续添加块
    [op addExecutionBlock:^{
        NSLog(@"下载书籍5 %@", [NSThread currentThread]);
    }];
    
    self.queue.maxConcurrentOperationCount = 2;
    [self.queue addOperation:op];

  输出结果:

  从结果看出,设置最大并发数不会限制执行块。一定要注意

3、最大并发数的应用场景

(1)用户在使用3G的时候

  限制线程的数量,省电,省流量(省钱)

(2)用户使用WIFI的时候(局域网)

  增加线程数量,提高用户的体验

五、队列的取消、暂停、恢复

1、取消队列的所有操作

  - (void)cancelAllOperations;

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

2、暂停和恢复队列

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

  - (BOOL)isSuspended;

六、操作优先级

  没事儿不要改优先级

(1)设置NSOperation在queue中的优先级,可以改变操作的执行优先级

  - (NSOperationQueuePriority)queuePriority;

  - (void)setQueuePriority:(NSOperationQueuePriority)p;

(2)优先级的取值
  NSOperationQueuePriorityVeryLow = -8L,
  NSOperationQueuePriorityLow = -4L,
  NSOperationQueuePriorityNormal = 0,
  NSOperationQueuePriorityHigh = 4,
  NSOperationQueuePriorityVeryHigh = 8

七、操作依赖

1、NSOperation之间可以设置依赖来保证执行顺序

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

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

    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(@"更新书架(UI),提示用户可以阅读 。。。 %@", [NSThread currentThread]);
    }];
    
    // 指定操作之间的”依赖“关系,某一个操作的执行,必须等待另一个操作完成才会开始
    // 依赖关系是可以跨队列指定的
    [op2 addDependency:op1];
    [op3 addDependency:op2];
    [op4 addDependency:op3];
    // *** 添加依赖的时候,注意不要出现循环依赖
    //    [op3 addDependency:op4];
    
    [self.queue addOperation:op1];
    [self.queue addOperation:op2];
    [self.queue addOperation:op3];
    // 主队列更新UI
    [[NSOperationQueue mainQueue] addOperation:op4];

  输出结果:

    正在下载图书。。。 <NSThread: 0x8c18b40>{name = (null), num = 2}

    正在解压缩图书。。。 <NSThread: 0x8c18b40>{name = (null), num = 2}

    正在保存到磁盘。。。 <NSThread: 0x8c18b40>{name = (null), num = 2}

    更新书架(UI),提示用户可以阅读。。。 <NSThread: 0x8e19030>{name = (null), num = 1}

  结果说明,操作依赖类似于串行队列,异步执行。

2、可以在不同queue的NSOperation之间创建依赖关系

3、注意:不能相互依赖,比如A依赖B,B依赖A

八、操作监听

  可以监听一个操作的执行完毕(没什么用)

  - (void (^)(void))completionBlock;

  - (void)setCompletionBlock:(void (^)(void))block;

九、自定义NSOperation的步骤很简单

1、重写- (void)main方法,在里面实现想执行的任务

   重写- (void)main方法的注意点

2、自己创建自动释放池(因为如果是异步操作,无法访问主线程的自动释放池)

  经常通过- (BOOL)isCancelled方法检测操作是否被取消,对取消做出响应

posted @ 2014-08-25 13:06  微博_裕之都  阅读(224)  评论(0编辑  收藏  举报