多线程NSOperation的详解

作者: wlw_花田半亩 | 来源:发表于2017-10-27 14:53 被阅读159次

NSOperation实现流程:

只要将NSOperation放入NSOperationQueue线程队列中,就会启动执行。

NSOperation是个抽象类,并不具备封装操作的能力,必须使用它的子类

使用NSOperation子类的方式有3种

1.NSInvocationOperation

1  创建Invocation线程

 NSInvocationOperation *invocationOperation =[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(loadImage)object:nil];

// 注意如果直接调用start方法,则此操作会在主线程中调用

// [invocationOperation start];//一般不会这么操作,而是添加到NSOperationQueue中

//创建线程队列

NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];

operationQueue.maxConcurrentOperationCount = 5; //设置最大并发线程数

//注意添加到线程队列后,队列里的线程就会开始执行

[operationQueue addOperation:invocationOperation];// 这里面就自动开始start 调用

补充:创建队列注意点:

 GCD:    串行类型:create & 主队列

              并发类型:create & 全局并发队列

NSOperation:

主队列:  [NSOperationQueue mainQueue] 和GCD中的主队列一样,串行队列

非主队列: [[NSOperationQueue alloc]init]  非常特殊(同时具备并发和串行的功能)

默认情况下,非主队列是并发队列

2.NSBlockOperation

方法一:创建Block线程

NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];

NSBlockOperation * blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{ }];

[operationQueue addOperation:blockOperation1];

NSBlockOperation * blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{ }];

[operationQueue addOperation:blockOperation1];

方法二:创建Block线程

NSOperationQueue * operationQueue = [[NSOperationQueue alloc] init];

[operationQueue addOperationWithBlock:^{        }];

补充: NSBlockOperation可以实现追加任务

给blockOperation 追加任务.

[blockOperation2 addExecutionBlock:^{NSLog(@"4----%@",[NSThread currentThread]);}];

[blockOperation2 addExecutionBlock:^{NSLog(@"5----%@",[NSThread currentThread]);}];

[blockOperation2 addExecutionBlock:^{NSLog(@"6----%@",[NSThread currentThread]);}];

3.自定义子类继承NSOperation,实现内部相应的方

创建一个  @interface LPOperation : NSOperation  继承NSOperation 的函数.

自定义子类

NSOperation常用函数场景

场景一 : 可以用到大文件下载时候,比如说下载暂停,取消,开始,

//  暂停,是可以恢复    [self.queue setSuspended:YES];

//   继续执行 [self.queue setSuspended:NO];

//   取消,不可以恢复  [self.queue cancelAllOperations];//该方法内部调用了所有操作的cancel方法

if(self.isCancelled) return;

NSLog(@"+++++++++++++++");

for (NSInteger i = 0; i<1000;i++ ) {

NSLog(@"download2---%zd--%@",i,[NSThread currentThread]);

}

场景二: NSOperation操作依赖和监听

- (void)loadImageWithMultiThread{

int count = 9;

NSOperationQueue *operationQueue = [[NSOperationQueue alloc]init];

operationQueue.maxConcurrentOperationCount = 5;//设置最大并发线程数

//创建加载最后一张图片的线程

NSBlockOperation *lastBlockOperation = [NSBlockOperation blockOperationWithBlock:^{

               [self loadImage:[NSNumber numberWithInt:(count-1)]];(调用下载函数)

}];

//创建多个线程用于下载其他图片

      for (int i=0; i < count -1 , i++){

   NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{

             [self loadImage:[NSNumber numberWithInt:i]];

   }];

    //设置依赖操作为最后一张图片加载操作,只有最后一张图片加载完成,其他图片才 开始陆续加载

            [blockOperation addDependency:lastBlockOperation];//这句话的意思就是lastBlockOperation这个操作依赖blockOperation这个操作,等blockOperation完成之后才调用.

             [operationQueue addOperation:blockOperation];

   }

       //将最后一个图片的加载线程加入线程队列

      [operationQueue addOperation:lastBlockOperation];

}

补充:操作监听 ,当blockOperation 完成时候再调用这个函数,但是不是立即调用,因为是多线程是无序的,只是代表blockOperation 的操作下一步会掉那个到任务中.

blockOperation.completionBlock = ^{

    NSLog(@"++++客官,来看我吧------%@",[NSThread currentThread]);

};


NSOperation 线程间的通信

需求案例:

1.下载图片1

2.下载图片2

3.合并图片

-(void)comBie

{

//1.创建队列

NSOperationQueue *queue = [[NSOperationQueue alloc]init];

__block UIImage *image1;

__block UIImage *image2;

//2 封装操作,下载图片1

NSBlockOperation *download1 = [NSBlockOperation blockOperationWithBlock:^{

NSURL *url = [NSURL URLWithString:@"http://s15.sinaimg.cn/bmiddle/4c0b78455061c1b7f1d0e"];

NSData *imageData = [NSData dataWithContentsOfURL:url];

image1 = [UIImage imageWithData:imageData];

NSLog(@"download---%@",[NSThread currentThread]);

}];

//3 封装操作,下载图片2

NSBlockOperation *download2 = [NSBlockOperation blockOperationWithBlock:^{

NSURL *url = [NSURL URLWithString:@"http://www.027art.com/feizhuliu/UploadFiles_6650/201109/2011091718442835.jpg"];

NSData *imageData = [NSData dataWithContentsOfURL:url];

image2 = [UIImage imageWithData:imageData];

NSLog(@"download---%@",[NSThread currentThread]);

}];

//4.封装合并图片的操作

NSBlockOperation *combie = [NSBlockOperation blockOperationWithBlock:^{

//4.1 开上下文

UIGraphicsBeginImageContext(CGSizeMake(200, 200));

//4.2 画图1

[image1 drawInRect:CGRectMake(0, 0, 100, 200)];

//4.3 画图2

[image2 drawInRect:CGRectMake(100, 0, 100, 200)];

//4.4 根据上下文得到图片

UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

//4.5 关闭上下文

UIGraphicsEndImageContext();

//7.更新UI

[[NSOperationQueue mainQueue] addOperationWithBlock:^{

self.imageView.image = image;

NSLog(@"UI----%@",[NSThread currentThread]);

}];

}];

//5.设置依赖关系

[combie addDependency:download1];

[combie addDependency:download2];

//6.添加操作到队列中

[queue addOperation:download2];

[queue addOperation:download1];

[queue addOperation:combie];

}

相关文章

网友评论

    本文标题:多线程NSOperation的详解

    本文链接:https://www.haomeiwen.com/subject/lmcrpxtx.html