美文网首页
NSOperation与NSOperationQueue的使用

NSOperation与NSOperationQueue的使用

作者: iOS_tree | 来源:发表于2024-01-08 15:01 被阅读0次

    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];
    

    相关文章

      网友评论

          本文标题:NSOperation与NSOperationQueue的使用

          本文链接:https://www.haomeiwen.com/subject/uligndtx.html