iOS多线程于NSOperationQueue和NSOperation

1、一个NSOperation(操作)对象默认是同步执行。若NSOperation添加到一个NSOperationQueue【即操作队列】中去执行,是异步执行。

操作队列为我们提供了两种不同类型的队列:主队列和自定义队列。主队列运行在主线程之上,而自定义队列在后台执行。

操作队列通过设置最大并发操作数(maxConcurrentOperationCount)来控制并发、串行(maxConcurrentOperationCount默认情况下为-1,表示不进行限制,可进行并发执行。为1时,队列为串行队列。只能串行执行。大于1时,队列为并发队列。操作并发执行,当然这个值不应超过系统限制,即使自己设置一个很大的值,系统也会自动调整为最小值)。

NSOperation 实现多线程的使用步骤分为三步:

-1-创建队列:创建 NSOperationQueue 对象。

NSOperationQueue *queue = [[NSOperationQueue alloc] init];

-2-创建操作:先将需要执行的操作封装到一个 NSOperation 对象中。

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

-3-将操作加入到队列中:将 NSOperation 对象添加到 NSOperationQueue 对象中。

[queue addOperation:operation];

添加一个block形式operation:

[queue addOperationWithBlock:^() {  
    NSLog(@"执行一个的操作,当前线程:%@", [NSThread currentThread]);  

2.NSOperation 是个抽象类,不能用来封装操作。我们只有使用它的子类来封装操作。以下是它的三种封装方式:

-1-使用子类 NSInvocationOperation;

-2-使用子类 NSBlockOperation;

-3-自定义继承自 NSOperation 的子类,通过实现内部相应的方法来封装操作。

2.1、使用子类NSInvocationOperation:

-(void)NSInvocationOperationMethod{
        // 1.创建 NSInvocationOperation 对象
        NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operation1) object:nil];
        // 2.开始执行操作
        [operation start];
   
}
//操作1
- (void)operation1 {
    for (int i = 0; i < 2; i++) {
        [NSThread sleepForTimeInterval:2]; // 模拟耗时操作
        NSLog(@"operation1---%@", [NSThread currentThread]);
    }
}
程序运行后输出结果:
可以看出:在没有使用 NSOperationQueue,在主线程中单独使用使用子类 NSInvocationOperation 执行一个操作的情况下,操作是在当前线程执行的,并没有开启新线程。

2.2、使用子类NSBlockOperation

- (void)NSBlockOperationMethod{
    
    // 1.创建 NSBlockOperation 对象
    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗时操作
            NSLog(@"operation---%@", [NSThread currentThread]);
        }
    }];
    
    // 2.开始执行操作
    [operation start];
}

程序运行后输出结果:


可以看出:和 NSInvocationOperation 使用一样,在没有使用 NSOperationQueue、在主线程中单独使用 NSBlockOperation 执行一个操作的情况下,操作是在当前线程执行的,并没有开启新线程。因为代码是在主线程中调用的,所以打印结果为主线程。如果在其他线程中执行操作,则打印结果为其他线程。

2.3、自定义继承自 NSOperation 的子类【嘤嘤嘤····此处停笔···因为结果是一样的:在没有使用 NSOperationQueue、在主线程单独使用自定义继承自 NSOperation 的子类的情况下,是在主线程中执行操作,并没有开启新线程。

3、接下来我们直接看看添加多个操作到操作队列中他们的执行顺序是怎样的:

首先先创建操作,将操作加入到创建好的队列中去:

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    // 创建3个操作
    NSOperation *a = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"operationA---%@",[NSThread currentThread]);
        
    }];
    NSOperation *b = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"operationB---%@",[NSThread currentThread]);
        
    }];
    NSOperation *c = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"operationC---%@",[NSThread currentThread]);
        
    }];

    // 执行操作
    [queue addOperation:a];
    [queue addOperation:b];
    [queue addOperation:c];

程序运行后输出结果:


可以看出是按顺序执行的。

接着我们加入依赖:

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    // 创建3个操作
    NSOperation *a = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"operationA---%@",[NSThread currentThread]);
        
    }];
    NSOperation *b = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"operationB---%@",[NSThread currentThread]);
        
    }];
    NSOperation *c = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"operationC---%@",[NSThread currentThread]);
        
    }];

    // 添加依赖
    [a addDependency:c];
    [a addDependency:b];
    // 执行操作
    [queue addOperation:a];
    [queue addOperation:b];
    [queue addOperation:c];

程序运行后输出结果:


可以看出A是最后执行的。但是,为什么不是先执行C再执行B呢?因为对于添加到queue中的operations,它们的执行顺序取决于2点:

1.不同于 GCD 中的调度队列 FIFO(先进先出)的原则,首先看看NSOperation是否已经准备好(是否准备好由对象的依赖关系确定);

2.然后再根据所有进入就绪状态的NSOperation的相对优先级来确定(非结束执行顺序)。优先级等级则是operation对象本身的一个属性。默认所有operation都拥有“普通”优先级,不过可以通过setQueuePriority:方法来提升或降低operation对象的优先级。优先级只能应用于相同queue中的operations。如果应用有多个operation queue,每个queue的优先级等级是互相独立的。因此不同queue中的低优先级操作仍然可能比高优先级操作更早执行。

优先级不能替代依赖关系,优先级只是对已经准备好的 operations确定执行顺序。先满足依赖关系,然后再根据优先级从所有准备好的操作中选择优先级最高的那个执行。

哪---在一边写这边文章一边搜罗问题的时候,看到https://www.jianshu.com/p/4b1d77054b35  这篇文~,挺详尽···

--···

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值