NSOperation慢慢整理

李明杰讲的简单易懂:http://blog.csdn.net/q199109106q/article/details/8566222

1. NSOperation

NSOperation是个抽象类,对GCD进行的封装,并不具备封装操作的能力,必须使⽤它的子类。
NSOperation的作⽤:配合使用NSOperation和NSOperationQueue也能实现多线程编程。

    // 开始对象运行
     - (void)start;
     // 同上,如果继承NSOperation,重写该方法。
     - (void)main;
     // 操作是取消状态
     @property (readonly, getter=isCancelled) BOOL cancelled;
     // 取消操作
     - (void)cancel;

     // 正在执行
     @property (readonly, getter=isExecuting) BOOL executing;
     // 已经完成
     @property (readonly, getter=isFinished) BOOL finished;
     // 是不是异步
     @property (readonly, getter=isConcurrent) BOOL concurrent; // To be deprecated; use and override 'asynchronous' below
     // 是不是异步
     @property (readonly, getter=isAsynchronous) BOOL asynchronous NS_AVAILABLE(10_8, 7_0);
     // 是不是可执行
     @property (readonly, getter=isReady) BOOL ready;

     // 添加依赖
     - (void)addDependency:(NSOperation *)op;
     // 取消依赖
     - (void)removeDependency:(NSOperation *)op;
     // 依赖对象数组
     @property (readonly, copy) NSArray<NSOperation *> *dependencies;

     // 优先级
     @property NSOperationQueuePriority queuePriority;
     // 对象完成之后的操作
     @property (nullable, copy) void (^completionBlock)(void);
     // 阻塞当前线程
     - (void)waitUntilFinished;
     // 线程优先级
     @property double threadPriority;
     // 操作名字
     @property (nullable, copy) NSString *name;
     // 服务质量,就是枚举
     @property NSQualityOfService qualityOfService;

注意:NSOperation添加到queue之后,绝对不要再修改NSOperation对象的状态。因为NSOperation对象可能会在任何时候运行,因此改变NSOperation对象的依赖或数据会产生不利的影响。你只能查看NSOperation对象的状态, 比如是否正在运行、等待运行、已经完成等。

2. NSOperation的子类

使用NSOperation⼦类的方式有3种:
1. NSInvocationOperation
2. NSBlockOperation
3. 自定义子类继承NSOperation,实现内部相应的⽅法(感觉没必要)

/**
     注意:NSOperation对象默认在主队列,主线程中执行,只有添加到队列中才会开启新的线程。
     即默认情况下,如果操作没有放到队列中queue中,都是同步执行。
     只有将NSOperation放到一个NSOperationQueue中,才会异步执行操作
    */

NSBlockOperation

 // 实例化NSBlockOperation
 + (instancetype)blockOperationWithBlock:(void (^)(void))block;
 // 添加执行代码块
 - (void)addExecutionBlock:(void (^)(void))block;
 // 获取执行代码块
@property (readonly, copy) NSArray<void (^)(void)> *executionBlocks;
 // 只要NSBlockOperation的block > 1,就会在主队列,异步执行操作
 // addExecutionBlock 必须添加到 [blockOperation start] 之前
    NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"NSBlockOperation--test1--%@",[NSThread currentThread]);
    }];

    [blockOperation addExecutionBlock:^{
         NSLog(@"NSBlockOperation--test2--%@",[NSThread currentThread]);
    }];

    [blockOperation addExecutionBlock:^{
        NSLog(@"NSBlockOperation--test3--%@",[NSThread currentThread]);
    }];

    [blockOperation start];

NSInvocationOperation

// 生成对象,target:执行sel的对象     sel:方法  arg:传给sel的参数对象
- (nullable instancetype)initWithTarget:(id)target selector:(SEL)sel object:(nullable id)arg;
// 下面有待研究
- (instancetype)initWithInvocation:(NSInvocation *)inv;
@property (readonly, retain) NSInvocation *invocation;
@property (nullable, readonly, retain) id result;
 //创建操作对象,封装要执行的任务
 NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(test) object:nil];
 //执行操作
 [invocationOperation start];

3. NSOperationQueue

// 添加NSOperation对象
- (void)addOperation:(NSOperation *)op;
// 添加NSOperation对象数组,如果wait == \(^o^)/YES!则阻塞当前线程,等待操作完成
- (void)addOperations:(NSArray<NSOperation *> *)ops waitUntilFinished:(BOOL)wait;

// 添加block,直接生成一个NSOperation对象
- (void)addOperationWithBlock:(void (^)(void))block;
// 添加的操作数组
@property (readonly, copy) NSArray<__kindof NSOperation *> *operations;
// 添加的操作个数
@property (readonly) NSUInteger operationCount;
// 最大线程数
@property NSInteger maxConcurrentOperationCount;
// 是否暂停 YES 暂停
@property (getter=isSuspended) BOOL suspended;
// 队列名字
@property (nullable, copy) NSString *name;

@property NSQualityOfService qualityOfService;

@property (nullable, assign /* actually retain */) dispatch_queue_t underlyingQueue NS_AVAILABLE(10_10, 8_0);

// 取消所有操作
- (void)cancelAllOperations;
// 等待所有操作完成,当前线程处于阻塞状态
- (void)waitUntilAllOperationsAreFinished;
// 获取当前队列
+ (nullable NSOperationQueue *)currentQueue;
// 获取主队列
+ (NSOperationQueue *)mainQueue;

NSOperation和NSOperationQueue实现多线程的具体步骤:
1. 先将需要执行的操作封装到一个NSOperation对象中
2. 然后将NSOperation对象添加到NSOperationQueue中
3. 系统会⾃动将NSOperationQueue中的NSOperation取出来
4. 将取出的NSOperation封装的操作放到⼀条新线程中执⾏

  // 队列是并行队列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    NSBlockOperation *blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"NSBlockOperation--test1--%@",[NSThread currentThread]);
    }];

    NSBlockOperation *blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"NSBlockOperation--test2--%@",[NSThread currentThread]);
    }];

    NSBlockOperation *blockOperation3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"NSBlockOperation--test3--%@",[NSThread currentThread]);
    }];
    NSBlockOperation *blockOperation4 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"NSBlockOperation--test4--%@",[NSThread currentThread]);
    }];

    // 添加代码块操作
    [queue addOperationWithBlock:^{
         NSLog(@"[%s]%d", __func__, __LINE__);
    }];

    [queue addOperations:@[blockOperation1, blockOperation2, blockOperation3, blockOperation4] waitUntilFinished:NO];

注意:NSOperation添加到queue之后,通常短时间内就会得到运行。但是如果存在依赖,或者整个queue被暂停等原因,也可能需要等待。

4.添加NSOperation的依赖对象

1.

当某个NSOperation对象依赖于其它NSOperation对象的完成时,就可以通过addDependency方法添加一个或者多个依赖的对象,只有所有依赖的对象都已经完成操作,当前NSOperation对象才会开始执行操作。另外,通过removeDependency方法来删除依赖对象。

[operation2 addDependency:operation1];
[operation2 removeDependency:operation1];

依赖关系不局限于相同queue中的NSOperation对象,NSOperation对象会管理自己的依赖, 因此完全可以在不同的queue之间的NSOperation对象创建依赖关系

唯一的限制是不能创建环形依赖,比如A依赖B,B依赖A,这是错误的

2.

依赖关系会影响到NSOperation对象在queue中的执行顺序,看下面的例子:

1> 没有设置依赖关系
    NSBlockOperation *block1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"block1--%@", [NSThread currentThread]);
    }];

    NSBlockOperation *block2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"block2--%@", [NSThread currentThread]);
    }];

    NSBlockOperation *block3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"block3--%@", [NSThread currentThread]);
    }];

    NSBlockOperation *block4 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"block4--%@", [NSThread currentThread]);
    }];

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue addOperation:block1];
    [queue addOperation:block2];
    [queue addOperation:block3];
    [queue addOperation:block4];  
打印信息:
2016-04-07 20:23:52.460 Test[1049:48861] block1--<NSThread: 0x7fd6bc000450>{number = 2, name = (null)}
2016-04-07 20:23:52.558 Test[1049:48859] block2--<NSThread: 0x7fd6b9f0e350>{number = 3, name = (null)}
2016-04-07 20:23:52.560 Test[1049:48886] block3--<NSThread: 0x7fd6b9c233b0>{number = 4, name = (null)}
2016-04-07 20:23:52.563 Test[1049:48851] block4--<NSThread: 0x7fd6b9c25020>{number = 5, name = (null)}
2> 设置了依赖关系
  NSBlockOperation *block1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"block1--%@", [NSThread currentThread]);
    }];

    NSBlockOperation *block2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"block2--%@", [NSThread currentThread]);
    }];

    NSBlockOperation *block3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"block3--%@", [NSThread currentThread]);
    }];

    NSBlockOperation *block4 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"block4--%@", [NSThread currentThread]);
    }];

    [block1 addDependency:block4];

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue addOperation:block1];
    [queue addOperation:block2];
    [queue addOperation:block3];
    [queue addOperation:block4];  

打印信息:

2016-04-07 20:25:09.799 Test[1074:51008] block4--<NSThread: 0x7fceead311d0>{number = 4, name = (null)}
2016-04-07 20:25:09.799 Test[1074:50994] block2--<NSThread: 0x7fceeaf3c4a0>{number = 2, name = (null)}
2016-04-07 20:25:09.799 Test[1074:51002] block3--<NSThread: 0x7fceeaf3a510>{number = 3, name = (null)}
2016-04-07 20:25:09.801 Test[1074:50994] block1--<NSThread: 0x7fceeaf3c4a0>{number = 2, name = (null)}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值