##iOS开发之NSOperationQueue

本文介绍iOS开发中NSOperationQueue的使用方法,包括NSOperation的不同子类及其实现方式,如何创建任务并添加到队列,设置队列的最大并发数,任务的挂起与取消,以及队列间任务的依赖关系。

##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]);
}

//打印结果:
 ------<NSThread: 0x7ffbd2f04040>{number = 1, name = main}

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

//
//下载一在主线程执行
下载1------<NSThread: 0x7ffe19408a20>{number = 1, name = main}
//下载二开启了新的线程 addExecutionBlock可以实现多线程异步操作
下载2------<NSThread: 0x7ffe19509be0>{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<UITouch *> *)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;
        }];
    }];
}
复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值