进程与线程:NSOperation

30 4月
  • NSThread
  • Runloop
  • 线程间通信
  • 线程间同步
  • GCD
  • NSOperation

NSThread,Runloop,线程间通信,线程间同步

点这里

GCD

点这里

NSOperation

GCD就是个block的封装,这在更复杂的场景下有点缺乏灵活性。IOS提供了NSOperation可以更灵活地支持线程间的切换,取消暂停任务等。

NSOperation相当于GCD更加面向对象的封装。可以将NSOperation类比成GCD里的block,NSOperationQueue类比成GCD里的队列。

NSOperation是个抽象类不能直接用,通常不需要程序员自己实现具体类,可以直接用系统提供的NSBlockOperationNSInvocationOperation两个具体类供大家使用。但例如AFNetworking就自己实现了具体类,需要自己实现NSOperation的KVO属性:

isReady      // 判断操作是否处于准备就绪状态,这个值和操作的依赖关系相关
isExecuting  // 判断操作是否正在在运行
isFinished   // 判断操作是否已经结束
isCancelled  // 判断操作是否已经标记为取消

日常开发最常用的就是NSOperation+NSOperationQueue配合使用,能让多线程编程非常简单(就像段子将大象放进冰箱要几个步骤):

  • 创建NSOperation对象,将需要执行的操作封装进去
  • 创建NSOperationQueue队列
  • 将NSOperation对象加入到NSOperationQueue队列中

NSOperationQueue用于管理operation的队列,底层使用libdispatch,可以设置最大并发数。

在NSOperationQueue中会自动忽略isAsynchronous(因为既然放入队列中就肯定是异步的),无法手动从队列中remove一个operation(但是可以调用operation的cancel方法取消一个operation),等所有operation执行完后(isFinished)会自动退出。

- (void)testNSOperationQueueOrder
{
      NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init]; // 创建NSOperationQueue队列
      // 创建NSOperation对象
      NSBlockOperation *lastBlockOperation = [NSBlockOperation blockOperationWithBlock:^{
          sleep(1);
          NSLog(@"最后的任务");
      }];
      for (int i = 0; i < 5; ++i) {  // 将NSOperation对象加入到NSOperationQueue对象中
          NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
              sleep(i);
              NSLog(@"第%d个任务",i);
          }];
          [blockOperation addDependency:lastBlockOperation];
          // 上面这行表示:所有任务都依赖这个前置任务,所以依次输出最后的任务,第0~4个任务
          // 如果注释掉上面这行,输出是乱序的,最后的任务会穿插在第0~4个任务之间输出
          [operationQueue addOperation:blockOperation];
      }
      [operationQueue addOperation:lastBlockOperation];
}

可以设置各个NSOperation的优先级:

- (void)testNSOperationQueuePriority
{
    NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
    operationQueue.maxConcurrentOperationCount = 1;  // 设置并发数为1,这样就等价于串行执行
    
    NSBlockOperation *blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"低优先级任务");
    }];
    blockOperation1.queuePriority = NSOperationQueuePriorityLow;
    
    NSBlockOperation *blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"高优先级任务");
        sleep(1);
    }];
    blockOperation2.queuePriority = NSOperationQueuePriorityHigh;
    
    NSBlockOperation *blockOperation3 = [NSBlockOperation blockOperationWithBlock:^{
        // 无意义的任务,目的是卡个时间
    }];
    
    [blockOperation1 addDependency:blockOperation3];
    [blockOperation2 addDependency:blockOperation3];
    
    [operationQueue addOperation:blockOperation1];
    [operationQueue addOperation:blockOperation2];  
    [operationQueue addOperation:blockOperation3];  // 依次输出高优先级任务,低优先级任务
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注