美文网首页
NSOperation的使用

NSOperation的使用

作者: 攻克乃还_ | 来源:发表于2017-12-01 18:01 被阅读13次
    • NSOperation是对GCD的包装
      两个核心概念【队列+操作】

    • NSOperation本身是抽象类,只能只有它的三个子类:
      NSBlockOperation NSInvocationOperation 自定义类继承NSOperation

    • NSOperation要和NSOperationQueue结合使用实现多线程并发

    一、NSOperation基本使用

    1.1.NSInvocationOperation

        //1.封装操作
        /*
         第一个参数:目标对象
         第二个参数:该操作要调用的方法,最多接受一个参数
         第三个参数:调用方法传递的参数,如果方法不接受参数,那么该值传nil
         */
        NSInvocationOperation *operation = [[NSInvocationOperation alloc]
                                            initWithTarget:self selector:@selector(run) object:nil];
        //2.启动操作
        [operation start];
    

    1.2.NSBlockOperation

        //1.封装操作
        /*
         NSBlockOperation提供了一个类方法,在该类方法中封装操作
         */
        NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
            //在主线程中执行
            NSLog(@"---download1--%@",[NSThread currentThread]);
        }];
        //2.追加操作,追加的操作在子线程中执行
        [operation addExecutionBlock:^{
            NSLog(@"---download2--%@",[NSThread currentThread]);
        }];
        //3.启动执行操作
        [operation start];
    

    1.3.自定义NSOperation

    • 自定义的类继承NSOperation,通过重写内部的main方法实现封装操作
        -(void)main {
            NSLog(@"--main--%@",[NSThread currentThread]);
        }
    
        //如何使用?
        //1.实例化一个自定义操作对象
        XMGOperation *op = [[XMGOperation alloc]init];
        //2.执行操作
        [op start];
    

    二、 NSOperationQueue基本使用

    GCD中的队列:
    • 串行队列:自己创建的/主队列
    • 并发队列:自己创建的/全局并发队列
    NSOperation中的两种队列:
    • 主队列:通过mainQueue获得。放到主队列中的任务都将在主线程执行

    • 非主队列:通过alloc init获得。非主队列同时具备了并发和串行的功能,通过设置最大并发数属性来控制任务是并发执行还是串行执行,默认并发

    • 2.1.NSInvocationOperation + NSOperationQueue

    - (void)invocation
    {
        //1.创建队列
        NSOperationQueue *queue = [[NSOperationQueue alloc]init];
        //2.封装操作
        NSInvocationOperation *op1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download1) object:nil];
        NSInvocationOperation *op2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download2) object:nil];
        //3.把封装好的操作添加到队列中
        [queue addOperation:op1];//[op1 start]
        [queue addOperation:op2];
    }
    
    • 2.2.NSBlockOperation + NSOperationQueue
    - (void)block
    {
        //1.创建队列
        NSOperationQueue *queue = [[NSOperationQueue alloc]init];
        //2.封装操作
        NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"1----%@",[NSThread currentThread]);
        }];
        NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"2----%@",[NSThread currentThread]);
        }];
        [op2 addExecutionBlock:^{
            NSLog(@"3----%@",[NSThread currentThread]);
        }];
        [op2 addExecutionBlock:^{
            NSLog(@"4----%@",[NSThread currentThread]);
        }];
        //3.添加操作到队列中
        [queue addOperation:op1];
        [queue addOperation:op2];
    
        //补充:简便方法
        [queue addOperationWithBlock:^{
            NSLog(@"5----%@",[NSThread currentThread]);
        }];
    }
    
    • 2.3.自定义NSOperation + NSOperationQueue
    -(void)customOperation
    {
        //1.创建队列
        NSOperationQueue *queue = [[NSOperationQueue alloc]init];
        //2.封装操作
        //好处:1.信息隐蔽 2.代码复用
        SUNOperation *op1 = [[SUNOperation alloc]init];
        SUNOperation *op2 = [[SUNOperation alloc]init];
        //3.添加操作到队列中
        [queue addOperation:op1];
        [queue addOperation:op2];
    }
    

    三、NSOperation其它操作

    a.设置最大并发数
    • 控制任务并发和串行
      • 最大并发数等于1,串行;大于1,并行
      • 系统的最大并发数有个默认的值:-1
      • 如果为0,不会执行任何任务
    • 要在任务添加到队列中之前进行设置
        //1.创建队列
        NSOperationQueue *queue = [[NSOperationQueue alloc]init];
        //2.设置最大并发数
        queue.maxConcurrentOperationCount = 2;
    
    b.暂停、恢复、取消
    • 设置暂停和恢复
      • suspended = YES表示暂停,NO表示恢复
      • 暂停表示不继续执行队列中的下一个任务,可以恢复
        if (self.queue.isSuspended) {
            self.queue.suspended = NO;
        }else {
            self.queue.suspended = YES;
        }
    
    c.取消队列里面的所有操作
    • 取消之后,当前正在执行的操作的下一个操作将不再执行,而且永远都不在执行,就像后面的所有任务都从队列里面移除了一样
    • 取消操作不可恢复
    • 苹果官方建议,每当执行完一次耗时操作之后,就查看一下当前队列是否为取消状态,如果是,那么就直接退出,以提高程序的性能

    [self.queue cancelAllOperations];

    // 自定义NSOperation取消操作
    -(void)main
    {
        //耗时操作1
        for (int i = 0; i<1000; i++) {
            NSLog(@"任务1-%d--%@",i,[NSThread currentThread]);
        }
        if (self.isCancelled) {
            return;
        }
        //耗时操作2
        for (int i = 0; i<1000; i++) {
            NSLog(@"任务1-%d--%@",i,[NSThread currentThread]);
        }
    }
    

    四、NSOperation线程间通信

        // 子线程下载图片
        NSOperationQueue *queue = [[NSOperationQueue alloc]init];
        [queue addOperationWithBlock:^{
            NSLog(@"下载图片--%@",[NSThread currentThread]);
            // 主线程刷新UI
            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                NSLog(@"刷新UI---%@",[NSThread currentThread]);
            }];
        }];
    

    五、设置操作依赖

    - (void)download2
    {
        //1.创建队列
        NSOperationQueue *queue = [[NSOperationQueue alloc]init];
        //2.封装操作:下载图片1
        NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        }];
        //3.封装操作:下载图片2
        NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        }];
        //4.封装操作:合成图片
        NSBlockOperation *combine = [NSBlockOperation blockOperationWithBlock:^{
            // 回到主线程刷新UI
            [[NSOperationQueue mainQueue]addOperationWithBlock:^{
                NSLog(@"刷新UI---%@",[NSThread currentThread]);
            }];
        }];
        //5.设置操作依赖
        [combine addDependency:op1];
        [combine addDependency:op2];
        //6.添加操作到队列中执行
        [queue addOperation:op1];
        [queue addOperation:op2];
        [queue addOperation:combine];
        }
    

    相关文章

      网友评论

          本文标题:NSOperation的使用

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