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];
    •  

 
posted @ 2016-06-20 18:26  朱峰博客  阅读(262)  评论(0编辑  收藏  举报