iOS-行知iOS 深度好文

多线程-NSOperation和NSOperationQueue

2017-02-14  本文已影响287人  進无尽

NSOperation

NSOperation类是用来封装在单个任务相关的代码和数据的抽象类。NSOperation 是苹果公司对 GCD 的封装,完全面向对象,所以使用起来更好理解。
** 因为它是用来封装任务的,大家可以看到 NSOperation 和 NSOperationQueue 分别对应 GCD 的 任务 和 队列,
但是NSOperation本身又有执行多线程的能力跟GCD里的任务还是有区别的** 。

操作步骤也很好理解:

创建任务

NSOperation 只是一个抽象类,所以不能封装任务。但它有 2 个子类用于封装任务。分别是:NSInvocationOperation 和 NSBlockOperation 。创建一个 Operation 后,需要调用 start 方法来启动任务,它会默认在当前队列同步执行。当然你也可以在中途取消一个任务,只需要调用其 cancel 方法即可。

 #.创建NSInvocationOperation对象
  NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];
  //开始执行
 [operation start];
 # 创建一个NSOperation不应该直接调用start方法(如果直接start则会在主线程中调用)而是应该放到NSOperationQueue中启动。

 #.创建NSBlockOperation对象
 NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"%@", [NSThread currentThread]);
  }];
  //开始任务
  [operation start];

注意:之前说过这样的任务,默认会在当前线程执行。但是 NSBlockOperation 还有一个方法:addExecutionBlock: ,通过这个方法可以给 Operation 添加多个执行 Block。这样 Operation 中的任务 会并发执行,它会 在主线程和其它的多个线程 执行这些任务.。并且ddExecutionBlock 方法必须在 start() 方法之前执行,否则就会报错。

# 创建NSBlockOperation对象
  NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
      NSLog(@"%@", [NSThread currentThread]);
  }];
# 添加多个Block
  for (NSInteger i = 0; i < 5; i++) {
      [operation addExecutionBlock:^{
          NSLog(@"第%ld次:%@", i, [NSThread currentThread]);
      }];
  }
  #开始任务,你会发现,会在多个线程中打印,其中包括主线程。
 [operation start];

自定义Operation

除了上面的两种 Operation 以外,我们还可以自定义 Operation。自定义 Operation 需要继承 NSOperation 类,并实现其 main() 方法,因为在调用 start() 方法的时候,内部会调用 main() 方法完成相关逻辑。所以如果以上的两个类无法满足你的欲望的时候,你就需要自定义了。你想要实现什么功能都可以写在里面。除此之外,你还需要实现 cancel() 在内的各种方法。

创建队列

我们可以调用一个 NSOperation 对象的 start() 方法来启动这个任务,这个默认是 同步执行 的。就算是 addExecutionBlock 方法,也会在 当前线程和其他线程 中执行,也就是说还是会占用当前线程。如果你不想这个任务在主线程中执行(代码默认情况下都在主线程中执行。)这是就要用到队列 NSOperationQueue 。按类型来说的话一共有两种类型:主队列、其他队列。只要添加到队列,会自动调用任务的 start() 方法。

NSOperationQueue的一些特殊使用

我们将 NSOperationQueue 与 GCD的队列 相比较就会发现,这里没有串行队列,那如果我想要10个任务在其他线程串行的执行的话,NSOperationQueue 有一个参数 maxConcurrentOperationCount 最大并发数,用来设置最多可以让多少个任务同时执行。当你把它设置为 1 的时候,就相当于是串行队列了

其他方法

以上就是一些主要方法, 下面还有一些常用方法需要大家注意:

#  NSOperation
BOOL executing; //判断任务是否正在执行
BOOL finished; //判断任务是否完成
#当一个 operation 被取消时,它的 completion block 仍然会执行,
#所以我们需要在真正执行代码前检查一下 isCancelled 方法的返回值。
- void (^completionBlock)(void); //用来设置完成后需要执行的操作
 
- (void)cancel; //取消任务
- (void)waitUntilFinished; //阻塞当前线程直到此任务执行完毕

#  NSOperationQueue
NSUInteger operationCount; //获取队列的任务数
- (void)cancelAllOperations; //取消队列中所有的任务
#阻塞当前线程直到此队列中的所有任务执行完毕
# **可以用来处理所有任务完成后的事件**
- (void)waitUntilAllOperationsAreFinished; 
[queue setSuspended:YES]; // 暂停queue
[queue setSuspended:NO]; // 继续queue
NSOperation和GCD的区别和类似的地方

小结

以上就是关于 NSOperation和NSOperationQueue 的主要知识了,后期如果有更多内容会同步更新。

上一篇 下一篇

猜你喜欢

热点阅读