KnightSama‘s Blog

vuePress-theme-reco KnightSama    2021
KnightSama‘s Blog KnightSama‘s Blog

Choose mode

  • dark
  • auto
  • light
首页
分类
  • iOS
  • 集锦
  • JavaScript
  • Github
  • Python
标签
时间线
GitHub
author-avatar

KnightSama

27

文章

14

标签

首页
分类
  • iOS
  • 集锦
  • JavaScript
  • Github
  • Python
标签
时间线
GitHub
  • 使用 NSOperation 并发编程

    • 创建操作
      • 使用 NSInvocationOperation 创建
      • 使用 NSBlockOperation 创建
      • 变更操作优先级
      • 操作完成回调
    • 创建队列
      • 主队列
      • 最大并发数
    • 队列的暂停、继续与取消
      • 队列暂停
      • 队列继续
      • 队列取消
    • 操作依赖

    使用 NSOperation 并发编程

    vuePress-theme-reco KnightSama    2021

    使用 NSOperation 并发编程


    KnightSama 2016-06-19 iOS Objective-C Swift

    在 iOS 中并发编程除了经常使用的 GCD 外还可以使用 NSOperation。与 GCD 相比 NSOperation 是面向对象的,所以更加易于使用,而且 NSOperation 包含了一些 GCD 较难实现的功能,也是苹果推荐的方式。

    NSOperation 的主要使用方式就是将操作添加到队列中,而 NSOperation 本身是个抽象类,其只有方法声明并没有实现,所以我们需要使用其子类来创建操作

    # 创建操作

    NSOperation 创建的操作默认都是异步执行的,可以通过调用 start 方法在当前线程立即执行操作

    # 使用 NSInvocationOperation 创建

    下面的例子中 demo 是一个普通的方法,NSInvocationOperation 只能在 Objective-C 中使用,Swift 已经移除了这种方法

    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(demo) object:nil];
    // 在当前线程立即执行操作
    [operation start];
    
    1
    2
    3

    # 使用 NSBlockOperation 创建

      NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
          // 操作 
      }];
      
      1
      2
      3
      let operation = BlockOperation {
          // 操作 
      }
      
      1
      2
      3

      我们可以通过 addExecutionBlock 给 NSBlockOperation 添加多个操作,这多个操作是异步执行的

        [operation addExecutionBlock:^{
            // 操作 
        }];
        
        1
        2
        3
        operation.addExecutionBlock {
            // 操作
        }
        
        1
        2
        3

        # 变更操作优先级

        我们可以通过设置 queuePriority 设置操作的优先级,通过设置 qualityOfService 设置操作的服务质量即系统分配资源的数量

          operation.queuePriority = NSOperationQueuePriorityHigh;
          operation.qualityOfService = NSOperationQualityOfServiceUserInteractive;
          
          1
          2
          operation.queuePriority = .high
          operation.qualityOfService = .userInteractive
          
          1
          2

          # 操作完成回调

          我们可以给操作设置回调函数,可以在操作执行完毕时执行

            [operation setCompletionBlock:^{
                // 操作结束时回调
            }];
            
            1
            2
            3
            operation.completionBlock = {
                // 操作结束时回调
            }
            
            1
            2
            3

            # 创建队列

            我们可以通过 NSOperationQueue 创建队列,将操作放入队列中运行。队列默认是并行的,我们可以通过将最大并发数设置为 1 来让队列变为串行

              // 创建队列
              NSOperationQueue *queue = [[NSOperationQueue alloc] init];
              // 向队列添加一个操作
              [queue addOperation:operation];
              
              1
              2
              3
              4
              // 创建队列
              let queue = OperationQueue()
              // 向队列添加一个操作
              queue.addOperation(operation)
              
              1
              2
              3
              4

              对于 NSBlockOperation 我们可以通过下面的方式直接向队列添加操作而无需单独创建

                // 创建队列
                NSOperationQueue *queue = [[NSOperationQueue alloc] init];
                // 向队列添加一个操作
                [queue addOperationWithBlock:^{
                    // 操作
                }];
                
                1
                2
                3
                4
                5
                6
                // 创建队列
                let queue = OperationQueue()
                // 向队列添加一个操作
                queue.addOperation {
                    // 操作
                }
                
                1
                2
                3
                4
                5
                6

                # 主队列

                我们可以通过下面的方式获得主队列,主队列是串行队列

                  NSOperationQueue *queue = [NSOperationQueue mainQueue];
                  
                  1
                  let queue = OperationQueue.main
                  
                  1

                  # 最大并发数

                  我们可以通过设置队列的 maxConcurrentOperationCount 参数来设置最大并发数,当该值设置为 1 时队列将以串行方式运行

                    queue.maxConcurrentOperationCount = 1
                    
                    1
                    queue.maxConcurrentOperationCount = 1
                    
                    1

                    # 队列的暂停、继续与取消

                    我们只能暂停与取消队列中还未执行的操作,正在执行的操作不受影响

                    # 队列暂停

                      queue.suspended = YES;
                      
                      1
                      queue.isSuspended = true
                      
                      1

                      注意

                      如果先暂停队列,再添加操作到队列,队列不会调度添加的操作。所以在暂停队列之前要判断队列中有没有任务,如果没有任务就不暂停队列。

                      # 队列继续

                        queue.suspended = NO;
                        
                        1
                        queue.isSuspended = false
                        
                        1

                        # 队列取消

                          [queue cancelAllOperations];
                          
                          1
                          queue.cancelAllOperations()
                          
                          1

                          # 操作依赖

                          如果一个操作需要另一个操作先完成则可以通过 addDependency 设置依赖。添加依赖需要在添加到队列前执行

                            NSBlockOperation *operationA = [NSBlockOperation blockOperationWithBlock:^{
                            }];
                            NSBlockOperation *operationB = [NSBlockOperation blockOperationWithBlock:^{
                            }];
                            // A 依赖于 B 先执行
                            [operationA addDependency:operationB];
                            
                            1
                            2
                            3
                            4
                            5
                            6
                            let operationA = BlockOperation {
                            }
                            let operationB = BlockOperation {
                            }
                            // A 依赖于 B 先执行
                            operationA.addDependency(operationB)
                            
                            1
                            2
                            3
                            4
                            5
                            6

                            注意

                            不能循环建立操作间依赖关系,否则队列不调度操作执行

                            欢迎来到 KnightSama‘s Blog
                            看板娘