iOS多线程网络之NSOperation

前面介绍了多线程中常用的GCD,链接:iOS多线程网络之GCD,这次介绍一下多线程网络中的另一个好用的技术NSOperation

简介

NSOperation和GCD差不多,但是NSOperation更加的面向对象,相当于对GCD的一个封装,NSOperation本身是一个抽象类,不具有封装操作的能力,即定义一个NSOperation对象不能进行多线程操作,要想实现操作,必须要使用到它的子类:NSInvocationOperation或NSBlockOperation,但是在使用其进行多线程操作的时候,必须先将其加入到NSOperationQueue队列中

使用方法

NSOperationQueue

NSOperationQueue队列类似于GCD中的主队列,GCD中队列分为:主队列,串行队列,并行队列,而NSOperationQueue只有两种:主队列,非主队列

  • 主队列
    我们没有办法直接创建主队列,但是可以通过创建非主队列然后获取到主队列
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];

加入到主队列的任务和GCD相同,不同创建新的线程,任务顺序执行

  • 非主队列
    我们通过NSOperationQueue的init方法创建的队列都为非主队列,即我们自定义的队列都为非主队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];

加入到非主队列的任务会自动创建新的线程执行任务,任务并行执行,加入到队列中的任务不用再调用start方法来执行,系统会创建线程自动执行

NSInvocationOperation

NSInvocationOperation直接使用init的创建方法,需要实现自定义的方法

NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(click1) object:nil];

定义好对象之后,调用start方法执行任务,此时定义的所有对象都是同步操作的,即不会开启新的线程执行任务

    NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(click1) object:nil];
    NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(click2) object:nil];
    NSInvocationOperation *op3 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(click3) object:nil];
    [op1 start];
    [op2 start];
    [op3 start];

执行结果:

但是当我们将对象加入到NSOperationQueue队列中后,即可开启新的线程执行任务

[queue addOperations:@[op1, op2, op3] waitUntilFinished:YES];

执行结果:

NSBlockOperation

NSBlockOperation采用block的创建方式,直接在block块中书写任务

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

定义好之后,调用start方法执行任务,但是同样的此时不会开启新的线程

    NSBlockOperation *block1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"block1-------%@",[NSThread currentThread]);
    }];
    NSBlockOperation *block2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"block2-------%@",[NSThread currentThread]);
    }];
    NSBlockOperation *block3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"block3-------%@",[NSThread currentThread]);
    }];
    [block1 start];
    [block2 start];
    [block3 start];

执行结果:

当我们将其加入到队列中之后,即可开启新的线程

[queue addOperations:@[block1, block2, block3] waitUntilFinished:YES];

执行结果:

使用NSBlockOperation的时候,我们还可以对其追加block任务,同样可以并发执行

[block1 addExecutionBlock:^{
        NSLog(@"block11--------%@",[NSThread currentThread]);
    }];

执行结果:

当然,我们使用NSBlockOperation的时候也可以创建一个没有任务的NSBlockOperation对象,然后对其进行追加.

那么问题来了,将两种对象加入到队列中能不能实现并行执行呢?
答案是可以

[queue addOperations:@[block1, block2, block3, op1, op2, op3] waitUntilFinished:YES];

执行结果:

最大并发数

NSOperation和GCD的一个区别就是可以设置并发数量,我们可以通过设置并发数量,来限制是否进行多线程操作

queue.maxConcurrentOperationCount = 5;

和GCD的区别

NSOperation既然是对GCD的封装,那么必然有着GCD不能实现的功能

取消任务

当我们设置了两个任务A和B,如果B要在A任务完成后使用A获得的数据进行任务,但是A任务因为网络问题执行失败,那么我们应该取消B任务来节省性能

//取消NSOperation任务
[op1 cancel];
//取消NSOperationQueue剩余的NSOperation任务
[queue cencelAllOperations]

设置依赖关系

还是A和B的例子,如果B必须要在A执行完之后再进行,如果是在主线程中,这个肯定是实现的,但是我们如果还想实现多线程,还是满足条件,怎么办呢?GCD中可以使用栅栏函数来实现这一功能,但是NSOperation更为简单,直接设置依赖即可,前提是两个任务都在队列中

//op2在op1执行完成之后执行
[op2 addDependency:op1];

注意:两者不能相互依赖,即op1依赖于op2,op2依赖于op1,这样会导致死锁

队列的暂停与恢复

这个更加简单,直接设置属性即可

[queue setSuspended:YES];//YES代表暂停队列,NO代表恢复队列

定义任务优先级

在GCD中,我们可以定义队列执行的优先级,但是在NSOperation中,我们可以定义任务的优先级,关于任务优先级,有五种类型:

typedef NS_ENUM(NSInteger, NSOperationQueuePriority) {
    NSOperationQueuePriorityVeryLow = -8L,
    NSOperationQueuePriorityLow = -4L,
    NSOperationQueuePriorityNormal = 0,
    NSOperationQueuePriorityHigh = 4,
    NSOperationQueuePriorityVeryHigh = 8
};

我们可以直接设置任务对象的优先级,但是设置了优先级一定就能保证优先执行吗?如果多个任务对象的优先级相同会怎么样呢?

    op1.queuePriority = NSOperationQueuePriorityVeryHigh;
    op2.queuePriority = NSOperationQueuePriorityVeryHigh;
    op3.queuePriority = NSOperationQueuePriorityVeryHigh;
    [queue addOperations:@[op1, op2, op3] waitUntilFinished:YES];

执行结果:

恩?好像是谁先设置谁先执行?别高兴的太早,我们再次运行试试看

这个时候就不一样了,这个需要注意

如何选择?

通过两篇文章的总结,我们可以注意到GCD通过block为单位,结构和C语言相似,更加的底层,处理相对较快,且使用简便,设置单个任务比NSOperation要简单.
而NSOperation可以设置并发数来限制线程,任务执行的顺序且任务可以被取消,队列可以暂停和恢复,更加的灵活.,对于多个任务的处理比GCD要更好控制.

欢迎来到我的博客,我是AnICoo1,我喂自己袋盐

有错误请评论指出或联系我,不胜感激!
个人邮箱:helloiamclh@gmail.com

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值