NSOperation

NSOperation在iOS 4后也基于GCD实现,但是相对于GCD来说可控性更强,并且可以加入操作依赖。NSOperation是一个抽象类,因此系统提供了NSBlockOperation和NSInvocationOperation两个子类,并且可以创建继承自NSOperation的自定义类。相比于GCD,NSOperation更加面向对象,开发者除了不需要去了解线程相关的概念之外,甚至连GCD中需要了解的异步/同步、并行/串行都不太需要深入了解,开发者只要懂得任务和队列即可。

NSBlockOperation类提供了如下操作方法,用于创建一个NSBlockOperation对象,任务封装在Block中。
+(instancetype)blockOperationWithBlock:(void (^)(void))block;
// 对于NSInvocationOperation类来说,需要执行的任务直接指定已定义的方法。
-(nullable instancetype)initWithTarget:(id)target selector:(SEL)sel object:(nullable id)tag;

2.无队列情况下执行任务
在不创建队列的情况下,可以直接调用NSOperation类的start方法来执行某个任务。
该任务是在当前线程进行执行的,如果是在主线程调用的start方法,那么则会在主线程中执行任务。
// 示例
-(void)executeInCurrentThread {
    NSBlockOperation *task1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"");
    }];
    NSBlockOperation *task2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"");
    }];
    // 调用start方法,会在当前线程中串行执行 
    [task1 start];
    [task1 start];
}
3.在队列中执行任务
当把任务放到队列(NSOperationQueue类)中进行执行时,系统会自动并行执行所有任务,
对于开多少条线程之类的事务,完全交由系统处理,开发者只要把任务添加到队列中即可。
另外,可以通过设置队列的maxConcurrentOperationCount属性,来设置并行执行任务的数量。
-(void)executeInQueue {
    NSBlockOperation *task1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"");
    }];
    NSBlockOperation *task2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"");
    }];
    NSBlockOperation *task3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"");
    }];
    // 创建队列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    // 设置队列属性
    queue.maxConcurrentOperationCount = 3;
    // 添加任务到队列
    [queue addOperation:task1];    
    [queue addOperation:task2];
    [queue addOperation:task3];
}
4.在任务中添加新任务
通过调用NSOperation类的addExecutionBlock方法,可以为某个NSOperation对象增加额外的任务。
当把这些新增的任务放到队列中执行时,也是并行执行的。
-(void)addExecutionBlock:(void (^)(void))block;
// 示例     在任务中添加新任务,所有的任务都会并行执行。
-(void)addTaskInOperation { 
    NSBlockOperation *task1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"task1---");
    }];
    // task1中添加task
    [task1 addExecutionBlock:^{
        NSLog(@"task1 add task ");
    }];
    // 创建队列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    // 添加任务到队列
    [queue addOperation:task1];  
}
5.在队列中直接添加任务
-(void) addTaskInQueue {
    NSBlockOperation *task1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"task1---");
    }];
    // task1中添加task
    [task1 addExecutionBlock:^{
        NSLog(@"task1 add task ");
    }];
     // 创建队列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    // 添加任务到队列
    [queue addOperation:task1]; 
    // 在queue中添加任务
    [queue addOperationWithBlock:^{
        NSLog(@"queue task --");
    }];
}
6.在任务中创建completionBlock
在NSOperation类中,可以通过设置completionBlock来创建所有任务执行完成后,自动调用的一个Block。
该Block的执行是在任务执行后被调用的,有先后顺序。
-(void)addCompletionBlock {
     NSBlockOperation *task1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"task1---");
    }];
    task1.completionBlock = ^{
        NSLog(@"task1 end ---");
    };
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue addOperation:task1]; 
}

NSOperation与GCD的区别

GCD是底层的C语言构成的API,而NSOperationQueue及相关对象是Objective-C的对象。在GCD中,在队列中执行的是由Block构成的任务,这是一个轻量级的数据结构;而NSOperation作为一个对象,提供了更多的选择。

在NSOperationQueue中,可以随时取消已经设定要准备执行的任务(当然,已经开始的任务就无法阻止了),而GCD没法停止已经加入queue的Block(其实是有的,但需要许多复杂的代码)。

NSOperation能够方便地设置依赖关系,可以让一个Operation依赖于另一个Operation,这样的话尽管两个Operation处于同一个并行队列中,但前者会直到后者执行完毕后再执行。

KVO可以应用在NSOperation中,可以监听一个Operation是否完成或取消,这样能比GCD更加有效地掌控执行的后台任务。

在NSOperation中,能够设置NSOperation的priority优先级,能够使同一个并行队列中的任务区分先后地执行。而在GCD中,只能区分不同任务队列的优先级,如果要区分Block任务的优先级,也需要大量的复杂代码。

用户能够对NSOperation进行继承,在这之上添加成员变量与成员方法,提高整个代码的复用度,这比简单地将Block任务排入执行队列更有自由度,能够在其之上添加更多自定制的功能。

线程间通信

// 示例
-(IBAction)downLoadImage:(id)sender {
    // 创建任务
    NSBlockOperation *downloadTask = [NSBlockOperation blockOperationWithBlock:^{
        // ...todo
        
        // 返回主线程 设置UI
        NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
        [mainQueue addOperationWithBlock:^{
            //
        }]
    }];
    // 创建队列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];   
    [queue addOperation:downLoadTask];
}

在GCD中可以使用队列组来设置任务之间的依赖关系,而在NSOperation中则提供了更加方便直观的方式来设置任务执行的先后顺序关系。通过NSOperation类中的addDependency方法,即可添加任务之间的依赖关系。由于addDependency是NSOperation类中的方法,与队列无关,因此也可以针对不同队列中的任务设置任务执行的先后依赖关系。

// 示例
-(IBAction)downLoadTwoImage:(id)sender {
    // 创建任务
    NSBlockOperation *task1= [NSBlockOperation blockOperationWithBlock:^{
        // ...todo
        
        // 返回主线程 设置UI
        NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
        [mainQueue addOperationWithBlock:^{
            //
        }]
    }];
    NSBlockOperation *task2= [NSBlockOperation blockOperationWithBlock:^{
        // ...todo
        
        // 返回主线程 设置UI
        NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
        [mainQueue addOperationWithBlock:^{
            //
        }]
    }];
    NSBlockOperation *task3= [NSBlockOperation blockOperationWithBlock:^{
        NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
        [mainQueue addOperationWithBlock:^{
            //
        }]
    }];
    // 设置任务之间依赖关系
    [task3 addDependency:task1];
    [task3 addDependency:task2];
    [task2 addDependency:task1];
    // 创建队列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];   
    [queue addOperation:task1];
    [queue addOperation:task2];
    [queue addOperation:task3];
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值