多线程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