zoukankan      html  css  js  c++  java
  • NSoperation的使用

    多线程----NSOperation详解

    字数1816 阅读197 评论6 
    简介
    • NSOpreation的作用
      p 配合NSOperation和NSOperationQueue也能够实现多线程编程

    • NSOperation 和 NSOperationQueue实现多线程的具体步骤
      p 先将需要执行的操作封装到一个NSOperation对象中
      p 然后将NSOperation对象添加到NSOperationQueue队列中
      p 系统会自动将NSOperationQueue中的NSOperation取出来
      p 将取出的NSOperation封装的操作放到一条新线程中执行

    NSOpreation的子类
    • NSOpreation是个抽象类,并不具备封装操作的能力,

    • 使用NSOperation子类的方式有3种
      NSInvocationOperation
      NSBlockOperation
      p 自定义子类继承NSOperation,实现内部相应的方法。

    NSInvocationOperation
    • 创建NSInvocationOperation对象
      NSInvocationOperation *p =[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];
    • 调用start方法开始执行操作
      -(void)start
      //一旦执行就会调用target的sel方法
    • 注意
      p 默认情况下,调用了start方法后并不会开启一条新线程去执行操作,而是在当前线程同步执行操作
      p 只有将NSOperation放到一个NSOperationQueue中,才会异步执行操作
         NSOperationQueue *queue = [[NSOperationQueue alloc] init];
         [queue addOperation:p];
      NSBlockOperation
    • 创建NSBlockOperation对象

      NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
      
            //在主线程中执行
            NSLog(@"%@",[NSThread currentThread]);
      
        }];
    • 通过- (void)addExecutionBlock:(void (^)(void))block;方法添加更多的操作
        //添加额外的任务(在子线程执行)
          [op addExecutionBlock:^{
            NSLog(@"----%@",[NSThread currentThread]);
          }];
           [op start];
    • 注意: 只要NSBlockOperation封装的操作数大于1 ,就会异步执行操作
    NSOperationQueue
    • NSOperationQueue的作用
      p NSOperation可以调用start方法来执行任务,但默认是同步执行的
      p 如果将NSOperation添加到NSOperationQueue(操作队列)中,系统会自动异步执行NSOperation中的操作
    • 添加操作到NSoperationQueue中
      - (void)addOperation:(NSOperation *)op;
      - (void)addOperationWithBlock:(void (^)(void))block;
    • (对比GCD)
      • GCD的队列类型
        • 并发队列
          • 自己创建的
          • 全局的
        • 串行队列
          • 主队列
          • 自己创建的
      • NSOperationQueue的队列类型
        • 主队列
          • [NSoperationQueue mainQueue]
          • 凡是添加到主队列中的任务,都会放到主线程中执行
        • 非主队列(其他队列)
          • [[NSOperationQueue alloc] init]
          • 同时包含了串行、并行功能
          • 添加到这种队列中的任务(NSOperation),就会被自动放到子线程中执行
    • 示例代码

      - (void)OperationQueue{
           //创建队列
            NSOperationQueue *queue = [[NSOperationQueue alloc] init];
      
            //创建操作(任务)
      
            //创建NSInvocationOperation
             NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task1) object:nil];
      
          NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task2) object:nil];
      
          //创建NSBlockOperation
          NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
      
              NSLog(@"task3 ---- %@",[NSThread currentThread]);
          }];
      
          [op3 addExecutionBlock:^{
      
              NSLog(@"task4 ---- %@",[NSThread currentThread]);
          }];
      
          [op3 addExecutionBlock:^{
      
              NSLog(@"task5 ---- %@",[NSThread currentThread]);
          }];
      
            [queue addOperation:op1];//内部会自动调 [op1 start];
            [queue addOperation:op2];//内部会自动调 [op2 start];
            [queue addOperation:op3];//内部会自动调 [op3 start];
            }
          - (void)task1{
              NSLog(@"task1----%@",[NSThread currentThread]);
          }
      
          - (void)task2{
              NSLog(@"task2----%@",[NSThread currentThread]);
          }
    • 自定NSOperation
      p 可以创建一个继承自NSOperation的类,在类的.m文件中重写方法- (void)main;

    将需要执行的任务写在main方法中,然后 创建队列,实例化自定义类,将实例添加到队列中,也可以开启新线程执行任务。

    p 示例代码

    - (void)lgjOperation{
    
        //创建队列
        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
        //创建自定义NSOperationQueue
        LGJNSOperation *operation = [[LGJNSOperation alloc] init];
    
        [queue addOperation:operation];//[operation start];
    
    }
    //自定义Operation类
    //.h文件
    #import <Foundation/Foundation.h>
    
    @interface LGJNSOperation : NSOperation
    
    @end
    
    //.m文件
    #import "LGJNSOperation.h"
    
    @implementation LGJNSOperation
    
    //
    -(void)main{
    
        NSLog(@"LGJNSOperation -- 下载图片---%@",[NSThread currentThread]);
    
    }
    
    @end
    最大并发数
    • 什么是并发数
      p 同时执行的任务数
      p 比如同时开三个线程,执行三个任务,最大并发数就是3

    • 最大并发数的相关方法

      - (NSInteger)maxConcurrentOperationCount;
      - (void)setMaxConcurrentOperationCount:(NSInteger)cnt;

      p 示例代码

      //最大并发数
      - (void)OperationQueue1{
      
          //创建队列
          NSOperationQueue *queue = [[NSOperationQueue alloc] init];
      
          //设置最大并发数
          //queue.maxConcurrentOperationCount = 2;
          queue.maxConcurrentOperationCount = 1;//变成了串行队列
      
          [queue addOperationWithBlock:^{
      
              NSLog(@"task1---%@",[NSThread currentThread]);
      
          }];
          [queue addOperationWithBlock:^{
      
              NSLog(@"task2---%@",[NSThread currentThread]);
      
          }];
          [queue addOperationWithBlock:^{
      
              NSLog(@"task3---%@",[NSThread currentThread]);
      
          }];
          [queue addOperationWithBlock:^{
      
              NSLog(@"task4---%@",[NSThread currentThread]);
      
          }];
      
      }
    队列的取消、暂停、恢复
    • 取消队列的所有操作
      - (void)cancelAllOperations;
      提示:也可以调用NSOperation的- (void)cancel方法取消单个操作
    • 暂停和恢复队列

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

      -示例代码1

           - (void)viewDidLoad {
           [super viewDidLoad];
      
          [self OperationQueue];
          }
      
          -(void)OperationQueue{
      
            NSOperationQueue *queue = [[NSOperationQueue alloc] init];
      
            queue.maxConcurrentOperationCount = 1;//设置为1就变成了串行队列
      
            //当执行了[self.queue cancelAllOperations];已经开启的线程是刹不住车的(意思是会继续打印),没有开启的线程将不会开启
            [queue addOperationWithBlock:^{
      
              for (NSInteger i = 0; i<1000 ; i++) {
      
                  NSLog(@"task1 - %zd- %@",i,[NSThread currentThread]);
              }
          }];
      
          [queue addOperationWithBlock:^{
      
            for (NSInteger i = 0; i<1000 ; i++) {
      
                NSLog(@"task2 - %zd- %@",i,[NSThread currentThread]);
            }
          }];
      
          [queue addOperationWithBlock:^{
      
            for (NSInteger i = 0; i<1000 ; i++) {
      
                NSLog(@"task3 - %zd- %@",i,[NSThread currentThread]);
            }
          }];
      
          self.queue = queue;
      
          }
      
          -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
      
            [self.queue cancelAllOperations];
      
        }
    • 示例代码2

          #import "ViewController.h"
          #import "LGJOperation.h"
          @interface ViewController ()
          @property(nonatomic,strong)NSOperationQueue *queue;
      
          @end
      
          @implementation ViewController
           - (void)viewDidLoad {
            [super viewDidLoad];
      
            [self OperationQueue];
          }
      
          -(void)OperationQueue{
      
            NSOperationQueue *queue = [[NSOperationQueue alloc] init];
      
            queue.maxConcurrentOperationCount = 1;//设置为1就变成了串行队列
      
            //开启一条线程 执行自定义operation任务,任务的具体内容封装在自定义类的main方法中
            LGJOperation *op = [[LGJOperation alloc] init];
      
            [queue addOperation:op];
      
            self.queue = queue;
      
          }
      
          -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
      
          [self.queue cancelAllOperations];
      
          }
          //自定义operation
          .h文件
          #import <Foundation/Foundation.h>
      
          @interface LGJOperation : NSOperation
      
          @end
          //.m文件
          #import "LGJOperation.h"
          @implementation LGJOperation
      
          -(void)main{
              for (NSInteger i = 0; i<5000 ; i++) {
                 //也可以在这里终止
                    if (i == 4000) {
      
                      if (self.cancelled)  return;
                }
            NSLog(@"task1 - %zd- %@",i,[NSThread currentThread]);
            }
          //如果想要终止线程中的任务,需要人为的做判断
            if (self.cancelled) return;
      
            for (NSInteger i = 0; i<1000 ; i++) {
      
                NSLog(@"task2 - %zd- %@",i,[NSThread currentThread]);
            }
            //可以在这里终止
            if (self.cancelled) return;
      
            for (NSInteger i = 0; i<1000 ; i++) {
      
                NSLog(@"task3 - %zd- %@",i,[NSThread currentThread]);
              }
      
            }
      
            @end
    • 示例代码2

          - (void)viewDidLoad {
            [super viewDidLoad];
      
              [self suspended];
      
            }
          //
           - (void)suspended{
      
            //创建队列
            self.queue1 =[[NSOperationQueue alloc] init];
      
            //设置最大并发数
            self.queue1.maxConcurrentOperationCount = 1;
      
            [self.queue1 addOperationWithBlock:^{
      
             [NSThread sleepForTimeInterval:2.0];
              NSLog(@"task1----%@",[NSThread currentThread]);
          }];
      
            [self.queue1 addOperationWithBlock:^{
            [NSThread sleepForTimeInterval:2.0];
            NSLog(@"task2----%@",[NSThread currentThread]);
          }];
          [self.queue1 addOperationWithBlock:^{
            [NSThread sleepForTimeInterval:2.0];
            NSLog(@"task3----%@",[NSThread currentThread]);
          }];
          }
          - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
      
            if (self.queue1.isSuspended) {
              //恢复队列,继续执行
              self.queue1.suspended = NO;
      
          }else{
              // 暂停(挂起)队列,暂停执行
              self.queue1.suspended = YES;
            }
          }
      操作依赖
    • NSOperation之间可以设置依赖来保证执行顺序
      p 比如一定要让操作A执行完以后,才能执行操作B,可以这么写

    • 示例代码

          - (void)viewDidLoad {
            [super viewDidLoad];
      
            [self Dependency];
      
          }
      
          //操作依赖
           - (void)Dependency{
      
          //创建队列
          NSOperationQueue *queue = [[NSOperationQueue alloc] init];
      
          NSInvocationOperation *operation1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run2:) object:@"1"];
      
          NSInvocationOperation *operation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run2:) object:@"2"];
      
          NSInvocationOperation *operation3 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run2:) object:@"3"];
          //设置依赖
          [operation1 addDependency:operation2];//1 依赖于 2
          [operation2 addDependency:operation3];//2 依赖于 3      
      
          [queue addOperation:operation1];
          [queue addOperation:operation2];
          [queue addOperation:operation3];
      
        }
      
         - (void)run2:(NSString*)obj{
      
              NSLog(@"[current thread]==%@---obj===%@",[NSThread   currentThread],obj);
      
          }
    • 可以在不同queue的NSOperation之间创建依赖关系


    屏幕快照 2016-06-17 上午10.48.51.png
    操作的监听
    • 可以监听一个操作的执行完毕

            - (void (^)(void))completionBlock;
            - (void)setCompletionBlock:(void (^)(void))block;
      • 示例代码

             NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        
             NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
        
             NSLog(@"task1 === %@",[NSThread currentThread]);
        
             }];
        
             operation1.completionBlock = ^{
        
                  NSLog(@"监听任务一执行完没1");
        
            };
        
          //    [operation1 setCompletionBlock:^{
          //        
          //        NSLog(@"监听任务一执行完没2");
          //    }];
        
            [queue addOperation:operation1];
      •  

     
  • 相关阅读:
    一个很诡异的javascript问题
    记录我开发鞋服行业供应链软件的历程<设计业务层>
    为什么要自已写报表中心
    关于系统的性能
    “时间”都去哪儿了?性能调优分析方法与案例详解
    工程师推荐软件
    终于有人把云计算、大数据和人工智能讲明白了!
    C# Dictionary 泛型字典集合(转)
    DEV中的TreeList控件应用的一个小效果实现
    推荐VS2008插件CodeRush Xpress for C#
  • 原文地址:https://www.cnblogs.com/zhufeng1994/p/5601463.html
Copyright © 2011-2022 走看看