NSOperation/NSOperationQueue

2018-12-05  本文已影响7人  liboxiang

参考链接:http://www.cocoachina.com/ios/20151201/14517.html

NSInvocationOperation

在其他线程中单独使用子类 NSInvocationOperation,操作是在当前调用的其他线程执行的,并没有开启新线程。

- (void)operationTest {
    NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(NSInvocationOperationAction:) object:@"haha"];
    [op start];
}

- (void)NSInvocationOperationAction:(NSString *)str {
    NSLog(@"test result = %@",str);
}

NSBlockOperation

使用子类 NSBlockOperation,并调用方法 AddExecutionBlock: 的情况下,blockOperationWithBlock:方法中的操作 和 addExecutionBlock: 中的操作是在不同的线程中异步执行的。而且,这次执行结果中 blockOperationWithBlock:方法中的操作也不是在当前线程(主线程)中执行的。从而印证了blockOperationWithBlock: 中的操作也可能会在其他线程(非当前线程)中执行。

一般情况下,如果一个 NSBlockOperation 对象封装了多个操作。NSBlockOperation 是否开启新线程,取决于操作的个数。如果添加的操作的个数多,就会自动开启新线程。当然开启的线程数是由系统来决定的。

- (void)operationTest {
    NSBlockOperation *block = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"test result = block operation");
        NSLog(@"block 线程:%@",[NSThread currentThread]);
    }];
    [block addExecutionBlock:^{
        NSLog(@"addExecutionBlock 开启新线程:%@",[NSThread currentThread]);
    }];
    [block start];
}

NSOperationQueue

NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(NSInvocationOperationAction:) object:@"queue haha"];
    
    NSBlockOperation *block = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"test queue result = block operation");
        NSLog(@"开启新线程:%@",[NSThread currentThread]);
    }];
    [block addExecutionBlock:^{
        NSLog(@"开启新线程:%@",[NSThread currentThread]);
    }];
    
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue addOperation:op];
    [queue addOperation:block];
    [queue addOperationWithBlock:^{
        NSLog(@"test queue add block");
        NSLog(@"开启新线程:%@",[NSThread currentThread]);
    }];
最大并发操作数:maxConcurrentOperationCount
NSOperation 操作依赖
NSOperation 优先级

NSOperation 提供了queuePriority(优先级)属性,queuePriority属性适用于同一操作队列中的操作,不适用于不同操作队列中的操作。默认情况下,所有新创建的操作对象优先级都是NSOperationQueuePriorityNormal。但是我们可以通过setQueuePriority:方法来改变当前操作在同一队列中的执行优先级。

// 优先级的取值
typedef NS_ENUM(NSInteger, NSOperationQueuePriority) {
    NSOperationQueuePriorityVeryLow = -8L,
    NSOperationQueuePriorityLow = -4L,
    NSOperationQueuePriorityNormal = 0,
    NSOperationQueuePriorityHigh = 4,
    NSOperationQueuePriorityVeryHigh = 8
};

queuePriority 属性决定了进入准备就绪状态下的操作之间的开始执行顺序。并且,优先级不能取代依赖关系。有依赖关系的,等依赖执行完之后才进入就绪状态

自定义继承自 NSOperation 的子类

非并发操作

一般只覆写main方法

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface TestOperation : NSOperation

@end

NS_ASSUME_NONNULL_END

@implementation TestOperation

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

@end
并发操作

实现并发操作要点:

  • 重写isConcurrent函数, 返回YES, 这个告诉系统各单位注意了我这个operation是要并发的.
  • 重写start()函数.
  • 重写isExecuting和isFinished函数

为什么在并发情况下需要自己来设定isExecuting和isFinished这两个状态量呢? 因为在并发情况下系统不知道operation什么时候finished, operation里面的task一般来说是异步执行的, 也就是start函数返回了operation不一定就是finish了, 这个你自己来控制, 你什么时候将isFinished置为YES(发送相应的KVO消息), operation就什么时候完成了.

上一篇下一篇

猜你喜欢

热点阅读