多线程 NSOperation

来源:互联网 发布:医疗大数据公司排名 编辑:程序博客网 时间:2024/04/30 11:22
苹果文档:
– removeDependency: 
删除指定的依赖关系

 NSOperation 是另一个”并发技术”,程序员不需要关心,,并发技术 不是多线程

NSOperation 
     - 核心概念:把操作(异步)添加到队列(全局的并发队列)!
     - 主队列 mainQueue
     - OC的框架 更加面向对象
     - 是对 GCD 的封装
     - iOS 2.0 推出的,苹果在推出GCD之后,对NSOperation的底成全部重写了.
     - 高级功能:
        - 最大操作并发数(GCD不好做)
        -在iOS 7.0 之前 使用GCD & NSOperation 能够开启的线程不多,5-6条
        - 从iOS 8.0 开始,能够开很多个线程,如果不控制,会造成资源浪费
       - 继续/暂停/全部取消
       - 依赖关系(CGD,同步认为是来制定依赖关系!)

GCD:
      - 将”任务(block)”添加到队列(串行/并发/主队列),并且指定执行的函数(同步/异步)
      - C 语言的框架 dispatch_xxx 函数
      - iOS 4.0 推出的,针对多核处理器的并发技术
      - iOS 4.0 推出的,针对多核处理器的并发技术
      -高级功能:
           -  一次性 once
           - 延迟操作 after
          - 调度组 (op可以做,但是太复杂) 

 The NSOperation class is an abstract class you use to encapsulate the code and data associated with a single task.
 - NSOperation
类是一个"抽象类",封装与一个任务关联的代码和数据
 -抽象类不能直接使用,需要使用子类

NSOperation 

 子类:
  * NSBlockOperation (块)
  * NSInvocationOperation(调度.用得少)

- 队列 NSOperationQueue

目前学过的抽象类
1. UIGestureRecognizer
 2. CAAnimation
 3. CAPropertyAnimation
(属性动画)
    - CABasicAnimation
(基本动画,fromValue, toValue
    - CAKeyframeAnimation
valuespath
    -通过修改图层的可动画属性


// MARK: - NSBlockOperation
// block operation将代码都写在一起,便于维护



// MARK: -更简单的
//只要是 NSOpeartion 的子类,都可以直接添加到队列!
// MARK: 线程间通讯
- (
void)opDemo5 {
   
    [
self.queueaddOperationWithBlock:^{
       
NSLog(@"耗时的操作%@", [NSThreadcurrentThread]);
      
       
// 在主线程更新 UI
        [[
NSOperationQueuemainQueue]addOperationWithBlock:^{
           
NSLog(@"更新UI %@", [NSThreadcurrentThread]);
        }];
    }];
}
- (void)opDemo4 {
   
// 通常在应用程序中,会用一个属性来记录 队列,全局管理所有的异步操作
//    NSOperationQueue *q = [[NSOperationQueue alloc] init];
   
   
// 直接向队列添加 block操作
   
for (int i = 0; i <10; ++i) {
        [
self.queueaddOperationWithBlock:^{
           
NSLog(@"%@ - %d", [NSThreadcurrentThread], i);
        }];
    }
   
   
// 向队列添加 NSBlockOperation
   
NSBlockOperation*op1 = [NSBlockOperationblockOperationWithBlock:^{
       
NSLog(@"BLOCK --- %@ - %d", [NSThreadcurrentThread],100);
    }];
    [
self.queueaddOperation:op1];
   
   
// invocation op
   
NSInvocationOperation*op2 = [[NSInvocationOperationalloc]initWithTarget:selfselector:@selector(downloadImage:)object:@"invocation"];
   
    [
self.queueaddOperation:op2];
}


- (void)opDemo3 {
   
NSOperationQueue*q = [[NSOperationQueuealloc]init];
   
   
for (int i = 0; i <10; ++i) {
       
// 操作
       
NSBlockOperation*op = [NSBlockOperationblockOperationWithBlock:^{
           
NSLog(@"%@ - %d", [NSThreadcurrentThread], i);
        }];
       
       
// 将操作添加到队列
        [q
addOperation:op];
    }
}


 NSOpeartion是对 GCD 的封装,是OC 的!比 GCD 的使用简单
 
 
队列:全局队列(并发队列)
 
操作:异步执行的任务
 */

- (
void)opDemo2 {
   
NSOperationQueue*q = [[NSOperationQueuealloc]init];
   
   
for (int i = 0; i <10; ++i) {
       
NSInvocationOperation*op = [[NSInvocationOperationalloc]initWithTarget:selfselector:@selector(downloadImage:)object:@(i)];
       
        [q
addOperation:op];
    }
}





- (void)opDemo1 {
   
// Invocation:调度,调用
   
// 提示:NSInvocation是一个非常古老的技术,暂时不建议大家学习和探索!
   
NSInvocationOperation*op = [[NSInvocationOperationalloc]initWithTarget:selfselector:@selector(downloadImage:)object:@"Invocation"];
   
   
// 启动操作,会在当前线程执行 @selector方法
//    [op start];
   
// 将操作添加到队列 -> 异步执行 @selector方法
   
NSOperationQueue*q = [[NSOperationQueuealloc]init];
    [qaddOperation:op];
 
}
- (void)downloadImage:(id)obj {
   
NSLog(@"%@ - %@", [NSThreadcurrentThread], obj);
}



 七. 最大并发数操作数
- (void)opDemo1 { 
   // 设置队列的最大并发操作数(队列是负责调度任务的)
 self.queue.maxConcurrentOperationCount =2;
   NSLog(@"start");
   for (int i = 0; i <20; ++i) {
        [
self.queueaddOperationWithBlock:^{
           
//休眠 效果?1秒钟之后,全部打印
            [NSThreadsleepForTimeInterval:1.0];
           NSLog(@"%@ - %d", [NSThreadcurrentThread], i);
        }];
    }
}


八.暂停/继续
- (IBAction)pauseAndResume {
  
   
// 判断队列中是否有操作,只有包含操作的时候,才继续后续操作
   
if (self.queue.operationCount== 0) {
       
NSLog(@"没有操作");
       
return;
    }
   
   
// 一旦设置了对列的挂起,再继续添加操作,操作都不会执行
   
self.queue.suspended= !self.queue.isSuspended;
   
   
if (self.queue.isSuspended) {
       
// 如果队列被挂起,operationCount中是包含没有执行完的操作数量
       
NSLog(@"暂停了%tu",self.queue.operationCount);
    }
else {
       
// 包含队列中所有要调度的操作
       
NSLog(@"继续%tu",self.queue.operationCount);
    }
}

// MARK:取消所有操作
// 案例:下载小电影,下载完第一个就后悔了,取消所有下载操作
- (
IBAction)cancelAll {
   
   
// 给队列发送取消操作的消息!
    [
self.queuecancelAllOperations];
   
   
// 直觉上会以为:cancelAllOperations一调用,队列中就没有操作了!
   
// 结果:cancelAllOperations方法是通知队列取消其中的操作,在队列取消完成之前,操作计数并不会发生变化!
   
// 包含正在执行中的操作+还没有调度的操作
   
NSLog(@"操作数量:%tu",self.queue.operationCount);
}


依赖关系
// MARK:依赖关系
// 举个栗子:用户登录,付费,下载,通知用户
- (
void)dependency {

   
NSBlockOperation*op1 = [NSBlockOperationblockOperationWithBlock:^{
       
NSLog(@"用户登录%@", [NSThreadcurrentThread]);
    }];
   
NSBlockOperation*op2 = [NSBlockOperationblockOperationWithBlock:^{
       
NSLog(@"付费%@", [NSThreadcurrentThread]);
    }];
   
NSBlockOperation*op3 = [NSBlockOperationblockOperationWithBlock:^{
        [
NSThreadsleepForTimeInterval:1.0f];
       
NSLog(@"下载%@", [NSThreadcurrentThread]);
    }];
   
NSBlockOperation*op4 = [NSBlockOperationblockOperationWithBlock:^{
       
NSLog(@"更新UI %@", [NSThreadcurrentThread]);
    }];

   
// 注意:在指定依赖关系时,注意不要出现循环依赖
   
// 另外:关于死不死,在不同iOS版本上不同,不同的 MAC 版本上表现都不一样
   
// 用户登录之前,先更新 UI
    [op1
addDependency:op4];
   
   
// waitUntilFinished == NO,异步的YES 是同步的
    [
self.queueaddOperations:@[op1, op2, op3]waitUntilFinished:NO];
   
   
// 更新UI的操作,应该由主队列来调度
    [[
NSOperationQueuemainQueue]addOperation:op4];
   
   NSLog(@"come here");

0 0
原创粉丝点击