##iOS开发之NSOperationQueue

iOS开发之NSOperationQueue

一. NSOperationQueue

  • NSOperation是个抽象类,并不具备封装操作的能力,必须使用其子类
    • NSInvocationOperation
    • NSBlockOperation
    • 自定义继承NSOperation
  • 配合使用NSOperation和NSOperationQueue能实现多线程编程.

NSInvocationOperation

- (void)invocationOperation
{
    //在当前线程中执行任务(主线程)
    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];

    [operation start];
}

- (void)run
{
    NSLog(@"------%@", [NSThread currentThread]);
}

//打印结果:
 ------{number = 1, name = main}

NSBlockOperation

- (void)blockOperation
{
    NSBlockOperation * operation = [NSBlockOperation blockOperationWithBlock:^{
        // 在主线程
        NSLog(@"下载1------%@", [NSThread currentThread]);
    }];
    
    // 添加额外的任务(在子线程执行)
    [operation addExecutionBlock:^{
        NSLog(@"下载2------%@", [NSThread currentThread]);
    }];
    
    [operation start];
}

//
//下载一在主线程执行
下载1------{number = 1, name = main}
//下载二开启了新的线程 addExecutionBlock可以实现多线程异步操作
下载2------{number = 2, name = (null)}

NSOperationQueue

1.NSOperation可以调用start的方法来执行任务,但是默认同步执行.

2.如果把NSOperation加到NSOperationQueue(操作队列)中,系统就会自动异步执行NSOperation中的任务.

NSOperationQueue的队列类型

  • 主队列
    • 添加到主队列的任务都会在主线程执行
[NSOperationQueue mainQueue];
  • 其他队列(串行,并行)

    • 同时包含了串行和并行的功能.
    • 添加到这种队列中的任务,都会自动放在子线程中执行.
    [[NSOperationQueue alloc]init];
    
    
  • 创建任务添加到队列

  NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    
    //创建操作
    //1.创建NSInvocationOperation任务
    NSInvocationOperation *operation1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(test1) object:nil];
    //2.创建NSBlockOperation任务
    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
       
        NSLog(@"test2---%@",[NSThread currentThread]);
        
    }];
    //3.创建自定义任务
    RKOperation *operation3 = [[RKOperation alloc]init];
    
    //4.队列添加Block任务
    [queue addOperationWithBlock:^{
        
          NSLog(@"test3---%@",[NSThread currentThread]);
    }];
    
    //添加到队列中,就执行了start的方法.
    [queue addOperation:operation1];
    [queue addOperation:operation2];
    [queue addOperation:operation3];

  • 设置队列的最大并发数
  queue.maxConcurrentOperationCount = 1;

当maxConcurrentOperationCount该队列的最大并发数,当maxConcurrentOperationCount = 1的时候,该队列就是串行队列,失去了并发功能.(queue就是通过这个属性来控制队列是串行还是并行).

  • 队列的任务的挂起(suspended)和取消(cancle)
    • 挂起(suspended)

    当有任务在执行的时候,当前正在执行的任务是不能挂起的,只能等该任务完成后,队列中其他任务就会被挂起了.

    - (void)viewDidLoad {
        [super viewDidLoad];
        self.queue = [[NSOperationQueue alloc]init];
        [self.queue addOperationWithBlock:^{
        for (int i = 0; i < 5000; i++) {
        
            NSLog(@"download1 --- %d---%@",i,[NSThread currentThread]);
        }
        
    }];
    [self.queue addOperationWithBlock:^{
        
        
        for (int i = 0; i < 5000; i++) {
            
            NSLog(@"download2 --- %d---%@",i,[NSThread currentThread]);
        }

    }];
    [self.queue addOperationWithBlock:^{

        for (int i = 0; i < 5000; i++) {
            
            NSLog(@"download3 --- %d---%@",i,[NSThread currentThread]);
        }

    }];
        [self.queue addOperationWithBlock:^{

        for (int i = 0; i < 5000; i++) {
            
              NSLog(@"download4 --- %d---%@",i,[NSThread    currentThread]);
        }

        }];

    }

    -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

    if(self.queue.suspended){
    
        self.queue.suspended = NO;
    }else{
    
        self.queue.suspended = YES;
    }
    }

    ```
    
    
 - 取消
   
    > 取消了就不能再次执行了,只能重新添加任务.
    >  当有任务在执行的时候,当前任务是不能取消的,会正在执行的任务执行完毕.队列中的其他任务就在执行了.

[self.queue cancelAllOperations];
   > 官方推荐自定义任务,在每个消耗时间的任务后都判断下cancle

      #import "RKOperation.h"
      @implementation RKOperation
    //在mian函数中写需要执行的任务.
    -(void)main{
                 for (int i = 0; i < 5000; i++) {
                NSLog(@"download1 --- %d---%@",i,[NSThread currentThread]);
              }
    if (self.isCancelled)  return;

    for (int i = 0; i < 5000; i++) {
    
        NSLog(@"download2 --- %d---%@",i,[NSThread currentThread]);
     }

    if (self.isCancelled)  return;

    for (int i = 0; i < 5000; i++) {
    
        NSLog(@"download3 --- %d---%@",i,[NSThread currentThread]);
    }

}

- 依赖

  >添加依赖要在addOperation之前设置. 也可以跨队列设置依赖.

  ```
/// 添加依赖,是operation3必须在operation1和operation2完成后再可以进行    
self.queue = [[NSOperationQueue alloc]init];
  
  NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
      
      NSLog(@"test1---%@",[NSThread currentThread]);

  }];
  
  NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
      
      NSLog(@"test2---%@",[NSThread currentThread]);

  }];
  
  NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
      
      NSLog(@"test3---%@",[NSThread currentThread]);

  }];
  //添加依赖,是operation3必须在operation1和operation2完成后再可以进行
  //添加依赖要在addOperation之前设置.
  [operation3 addDependency:operation1];
  [operation3 addDependency:operation2];

  [self.queue addOperation:operation1];
  [self.queue addOperation:operation2];
  [self.queue addOperation:operation3];
  
  • 线程间的通信
/**
 * 线程之间的通信
 */
- (void)test
{
    [[[NSOperationQueue alloc] init] addOperationWithBlock:^{
        // 图片的网络路径
       NSURL *url = [NSURL URLWithString:@"http://img.pconline.com.cn/images/photoblog/9/9/8/1/9981681/200910/11/1255259355826.jpg"];
     
        
        // 加载图片
        NSData *data = [NSData dataWithContentsOfURL:url];
        
        // 生成图片
        UIImage *image = [UIImage imageWithData:data];
        
        // 回到主线程
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            self.imageView.image = image;
        }];
    }];
}

你可能感兴趣的:(##iOS开发之NSOperationQueue)