多线程开发(NSOperation)

383 阅读3分钟
  1. NSOperation、NSOperationQueue 简介 好处
  • 基于 GCD 更高一层的封装,完全面向对象。但是比 GCD 更简单易用、代码可读性也更高。
  • 可添加完成的代码块,在操作完成后执行。
  • 添加操作之间的依赖关系,方便的控制执行顺序。
  • 设定操作执行的优先级。
  • 可以很方便的取消一个操作的执行。
  • 使用 KVO 观察对操作执行状态的更改:isExecuteing、isFinished、isCancelled。
  1. 使用 使用 NSOperation 子类 NSInvocationOperation、NSBlockOperation,或者自定义子类来封装操作。是非线程安全。
// 
1.创建 NSInvocationOperation 对象
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task) object:nil];
// 2.调用 start 方法开始执行操作
[op start];
  
  NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
  	// todo
  }];
  [op start];
  1. 使用自定义继承自 NSOperation 的子类,是在主线程操作
// XQOperation.h 文件
#import <Foundation/Foundation.h>

@interface XQOperation : NSOperation

@end

// YSCOperation.m 文件
#import "XQOperation.h"

@implementation XQOperation

- (void)main {
    if (!self.isCancelled) {
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"1---%@", [NSThread currentThread]);
        }
    }
}

@end

// 1.创建 YSCOperation 对象
    XQOperation *op = [[XQOperation alloc] init];
    // 2.调用 start 方法开始执行操作
    [op start];
  1. NSOperationQueue使用,也可以直接 通过- (void)addOperationWithBlock:(void (^)(void))block;进行操作block。可以设置最大并发数,为1时是串行,>1 时并行。
// 1.创建队列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    // 2.创建操作
    // 使用 NSInvocationOperation 
    NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task1) object:nil];

    // 使用 NSInvocationOperation 
    NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task2) object:nil];

    // 使用 NSBlockOperation 
    NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        // todo
    }];
    [op3 addExecutionBlock:^{
        // todo
        }];

    // 3.使用 addOperation: 添加所有操作到队列中
    [queue addOperation:op1]; // [op1 start]
    [queue addOperation:op2]; // [op2 start]
    [queue addOperation:op3]; // [op3 start]
  1. NSOperation 操作依赖,通过如下方法可以设置依赖
  • - (void)addDependency:(NSOperation *)op;
  • - (void)removeDependency:(NSOperation *)op;
  • @property (readonly, copy) NSArray<NSOperation *> *dependencies;
  1. NSOperation 常用属性和方法
取消操作方法
- (void)cancel; 可取消操作,实质是标记 isCancelled 状态。
判断操作状态方法
- (BOOL)isFinished; 判断操作是否已经结束。
- (BOOL)isCancelled; 判断操作是否已经标记为取消。
- (BOOL)isExecuting; 判断操作是否正在在运行。
- (BOOL)isReady; 判断操作是否处于准备就绪状态,这个值和操作的依赖关系相关。
操作同步
- (void)waitUntilFinished; 阻塞当前线程,直到该操作结束。可用于线程执行顺序的同步。
- (void)setCompletionBlock:(void (^)(void))block; completionBlock 会在当前操作执行完毕时执行 completionBlock。
- (void)addDependency:(NSOperation *)op; 添加依赖,使当前操作依赖于操作 op 的完成。
- (void)removeDependency:(NSOperation *)op; 移除依赖,取消当前操作对操作 op 的依赖。
@property (readonly, copy) NSArray<NSOperation *> *dependencies; 在当前操作开始执行之前完成执行的所有操作对象数组。
  1. NSOperationQueue 常用属性和方法
取消/暂停/恢复操作
- (void)cancelAllOperations; 可以取消队列的所有操作。
- (BOOL)isSuspended; 判断队列是否处于暂停状态。 YES 为暂停状态,NO 为恢复状态。
- (void)setSuspended:(BOOL)b; 可设置操作的暂停和恢复,YES 代表暂停队列,NO 代表恢复队列。
操作同步
- (void)waitUntilAllOperationsAreFinished; 阻塞当前线程,直到队列中的操作全部执行完毕。
添加/获取操作`
- (void)addOperationWithBlock:(void (^)(void))block; 向队列中添加一个 NSBlockOperation 类型操作对象。
- (void)addOperations:(NSArray *)ops waitUntilFinished:(BOOL)wait; 向队列中添加操作数组,wait 标志是否阻塞当前线程直到所有操作结束
- (NSArray *)operations; 当前在队列中的操作数组(某个操作执行结束后会自动从这个数组清除)。
- (NSUInteger)operationCount; 当前队列中的操作数。
获取队列
+ (id)currentQueue; 获取当前队列,如果当前线程不是在 NSOperationQueue 上运行则返回 nil。
+ (id)mainQueue; 获取主队列。