NSOperation与NSOperationQueue的使用

2024-01-08  本文已影响0人  iOS_tree

1.NSOperation

NSOperation是苹果提供的一种多线程方案。与GCD相比,属于面向对象层面开发。
我们不能直接使用NSOperation,需要使用它的子类进行创建任务。
NSOperation系统提供的子类有:NSInvocationOperation、NSBlockOperation。我们也可以自己定义NSOperation,实现main方法。

1.1NSInvocationOperation

NSInvocationOperation使用比较简单,创建对象,调用会想的start方法即可。如下:

//阻塞当前线程,在当前线程执行
NSInvocationOperation *operaton = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];
[operaton start];

run方法如下所示:

- (void)run {
    NSLog(@"%@",[NSThread currentThread]);
}

1.2NSBlockOperation

NSBlockOperation首先创建对象,然后执行start方法,可以添加多个任务。添加的第一个任务会阻塞当前线程,addExecutionBlock添加的任务不会阻塞,会在子线程执行。

    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        sleep(2);
        //阻塞当前线程,在当前线程执行
        NSLog(@"%@",[NSThread currentThread]);
    }];
    [operation addExecutionBlock:^{
        //不阻塞当前线程,在子线程执行
        NSLog(@"block 2 %@",[NSThread currentThread]);
    }];
    [operation start];

1.3自定义NSOperation子类

自定义NSOperation子类,实现main方法,把任务代码写在main方法即可,自定义也会阻塞当前线程执行。代码如下:

@interface ESCOperation : NSOperation

@end
@implementation ESCOperation

- (void)main{
    NSLog(@"%@",[NSThread currentThread]);
}

@end

调用如下:

    ESCOperation *operation = [[ESCOperation alloc] init];
    //阻塞当前线程执行
    [operation start];

2.NSOperationQueue

NSOperationQueue是操作队列,和GCD的queue有些类似,可以往NSOperationQueue队列中添加NSOperation,有自定义的NSOperationQueue对象,也可以获取主线程NSOperationQueue对象,往主线程NSOperationQueue对象中添加任务,任务则在主线程执行,同时我们可以设置任务完成回调,监听任务完成情况,用法如下:

    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        //子线程执行
        NSLog(@"%@",[NSThread currentThread]);
    }];
    [operation setCompletionBlock:^{
        //任务完成调用的方法
        NSLog(@"completion %@",[NSThread currentThread]);
    }];
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue addOperation:operation];

也可以直接添加block,如下:

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue addOperationWithBlock:^{
        NSLog(@"3 %@",[NSThread currentThread]);
    }];

获取主线程NSOperationQueue对象,添加任务

    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        //主线程执行
        NSLog(@"%@",[NSThread currentThread]);
    }];
    [operation setCompletionBlock:^{
        //子线程执行
        NSLog(@"completion %@",[NSThread currentThread]);
    }];
    NSOperationQueue *queue = [NSOperationQueue mainQueue];
    [queue addOperation:operation];

NSOperationQueue提供了addBarrierBlock方法,保证任务的独立执行,方法如下:

/// @method addBarrierBlock:
/// @param barrier      A block to execute
/// @discussion         The `addBarrierBlock:` method executes the block when the NSOperationQueue has finished all enqueued operations and
/// prevents any subsequent operations to be executed until the barrier has been completed. This acts similarly to the
/// `dispatch_barrier_async` function.
- (void)addBarrierBlock:(void (NS_SWIFT_SENDABLE ^)(void))barrier API_AVAILABLE(macos(10.15), ios(13.0), tvos(13.0), watchos(6.0));

当我们有如下任务时,可使用该方法


image.png

代码如下:

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue addOperationWithBlock:^{
        NSLog(@"任务1 %@",[NSThread currentThread]);
        sleep(2);
    }];
    [queue addOperationWithBlock:^{
        NSLog(@"任务2 %@",[NSThread currentThread]);
    }];
    [queue addOperationWithBlock:^{
        NSLog(@"任务3 %@",[NSThread currentThread]);
    }];
    [queue addBarrierBlock:^{
        NSLog(@"任务4 %@",[NSThread currentThread]);
        sleep(1);
    }];
    [queue addOperationWithBlock:^{
        NSLog(@"任务5 %@",[NSThread currentThread]);
    }];
    [queue addOperationWithBlock:^{
        NSLog(@"任务6 %@",[NSThread currentThread]);
    }];
    [queue addOperationWithBlock:^{
        NSLog(@"任务7 %@",[NSThread currentThread]);
    }];

我们可以设置队列的最大并发数,属性如下:

@property NSInteger maxConcurrentOperationCount;

设置为0时不执行任务。
我们也可以设置优先级,包括NSOperation对象和NSOperationQueue对象,属性如下:

typedef NS_ENUM(NSInteger, NSQualityOfService) {
    NSQualityOfServiceUserInteractive = 0x21,
    NSQualityOfServiceUserInitiated = 0x19,
    NSQualityOfServiceUtility = 0x11,
    NSQualityOfServiceBackground = 0x09,
    NSQualityOfServiceDefault = -1
} API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));

@property NSQualityOfService qualityOfService API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));

可以暂停(继续)当前后续任务的执行:

@property (getter=isSuspended) BOOL suspended;

可以取消所有后续任务:

- (void)cancelAllOperations;

当我们有任务1和任务2,且任务1必须依赖任务2,意思就是说任务1必须等任务2执行完毕后才能执行,可以设置任务间的依赖来实现此功能。代码如下:

  NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
        //子线程执行
        NSLog(@"operation1 %@",[NSThread currentThread]);
    }];
    
    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
        //子线程执行
        NSLog(@"operation2 %@",[NSThread currentThread]);
    }];
    //operation1依赖operation2的执行,operation1必须在operation2执行完毕后再执行
    [operation1 addDependency:operation2];
   
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue addOperation:operation1];
    [queue addOperation:operation2];
上一篇下一篇

猜你喜欢

热点阅读