iOS开发之NSOperation深入浅出

NSOperation的核心概念和GCD非常相似,NSOperation是将“操作”添加到“队列”中。NSOperation是一个抽象类,不能直接使用,其目的就是为了定义子类共有的方法和属性。其子类有两个:NSInvocationOperation、NSBlockOperation。(废话不多说,直接上代码👇)

一、NSInvocationOperation

- (void)viewDidLoad {
    [super viewDidLoad];
    //1.队列
    NSOperationQueue * q = [[NSOperationQueue alloc]init];
    
    for (int i = 0; i < 10; i++) {
         //初始化NSInvocationOperation,执行一个操作。
         NSInvocationOperation * op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadImage:) object:@(i)];
        
        //添加到队列
        [q addOperation:op];
    }
    
}

- (void)downloadImage:(id)objc {
    NSLog(@"%@  %@",[NSThread currentThread],objc);
}

打印结果:


image.png

这个结果告诉我们:开启多个线程,不会顺序执行 --> GCD 并发队列,异步执行

队列:本质上就是GCD的并发队列!!!
操作:就是异步执行任务!!!

二、NSBlockOperation

-(void) viewDidLoad{
    [super viewDidLoad];
    //1.队列
    NSOperationQueue * q = [[NSOperationQueue alloc]init];
    //2.操作
    for (int i = 0; i < 10; i++) {
        NSBlockOperation * op = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"%@ --- %d",[NSThread currentThread],i);
        }];
        //添加到队列
        [q addOperation:op];
    }
}

结果就不多说了,肯定和NSInvocationOperation一样的。但是,你们有木有发现,NSBlockOperation使用起来更加方便简单呢,而且代码都在一起,便于维护!!!

就是这么简单,其实NSOperation到这里就差不多讲完了。。(别,别动手,不准打脸。我再写点东西出来。。。)

还有一个更加简单的方法哈,👀👇!!!

在开发过程中,我们肯定要使用全局队列的。先声明一个全局队列属性

@property(nonatomic,strong)NSOperationQueue * opQueue;

再懒加载一下

//懒加载
-(NSOperationQueue *)opQueue
{
    if (!_opQueue) {
        _opQueue = [[NSOperationQueue alloc]init];
    }
    return _opQueue;
}

重点来了

-(void) viewDidLoad{
    [super viewDidLoad];
    //直接添加任务
    for (int i = 0; i < 10; i++) {
        [self.opQueue addOperationWithBlock:^{
            NSLog(@"%@ --- %d",[NSThread currentThread],i);
        }];
    }
}

在NSOperation里没有最简单,只有更简单。哈哈😀!
结果就不用看了吧,和上面一样哦!!!

提示:只要是NSOperation 的子类,都可以添加到队列!

三、线程间的通讯

-(void) viewDidLoad{
    [super viewDidLoad];
    [self.opQueue addOperationWithBlock:^{
        NSLog(@"耗时操作  %@",[NSThread currentThread]);
        //主线程更新 UI
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            NSLog(@"UIJIUUIIUIU   --- %@",[NSThread currentThread]);
        }];
        
    }];
}

上面这段代码就不讲解了,一眼就看懂了!!!

NSOperaton 是苹果大力推荐的"并发"技术!

小结:

GCD & NSOperation 对比

GCD 在 iOS 4.0 推出,主要针对多核处理器做了优化的并发技术,是C语言的
- 将"任务"[block]添加到 队列[串行/并发/主队列/全局队列] ,并且指定执行任务的函数[同步/异步]
- 线程间的通讯 dispatch_get_main_queue()
- 提供了一些 NSOperation 不具备的功能
- 一次执行
- 延迟执行
- 调度组(在op中也可以做到,有点麻烦)

NSOperation 在 iOS 2.0 推出的,苹果推出 GCD以后,对NSOperation 底层做了重写!
- 将操作[异步执行的任务] 添加到队列[并发队列],就会立刻异步执行
- 线程间的通讯mainQueue
- 提供了一些GCD 实现起来比较困难的功能
- 最大并发线程
- 队列的暂停/继续
- 取消所有操作
- 指定操作之间的依赖关系(GCD 用同步来实现)

四、最大并发数

/*
从 iOS 8.0 开始,无论使用 GCD还是 NSOperation ,都会开启很多线程
在 iOS 7.0 以前,GCD 通常只会开启 5 6条线程!
目前线程多了说明:
1.底层的现场池更大了,能够拿到的线程资源多了!
2.多控制同时并发的现场数,要求就更高了!
*/

-(void)viewDidLoad{
    [super viewDidLoad];
    //设置同时最大的并发操作数量
    //WIFI: 5 至 6
    //流量 : 2 到 3
    self.opQueue.maxConcurrentOperationCount = 2;
    
    
    //添加操作进队列  
    for (int i = 0;i < 20; i++) {
        [self.opQueue addOperationWithBlock:^{
            //当前线程睡一秒
            [NSThread sleepForTimeInterval:1.0];
            NSLog(@"%@---%d",[NSThread currentThread],i);
        }];
    }
}

打印结果:


image.png

先看时间:每隔一秒,打印两次。没毛病吧,最大并发数为2嘛!!!
再看线程数:(别丢鸡蛋啊,我还没讲完。。。)有人就说了不是最大并发数为2嘛,线程数5和6是哪里来的?看下面!!!

知识点补充:子线程在完成任务以后,线程池会对其进行回收。上个任务执行完毕后,也会有调度下个任务的操作。当回收线程和调度任务相遇,那么就会产生新线程了。线程在回收的过程中,就不能执行任务了。这时就少了一个线程,所以线程池会再分配一条线程出来执行任务。所以5和6就这样产生了,并不是我忽悠你们啊。真的最多就只有两条线程(除主线程外,切记!!!)

五、队列挂起&取消所有操作

1、暂停&继续

    //判断我们队列是否挂起
    if(self.opQueue.isSuspended){
        NSLog(@"继续 %tu",self.opQueue.operationCount);
        self.opQueue.suspended = NO;
    }else{
        NSLog(@"暂停%tu",self.opQueue.operationCount);
        self.opQueue.suspended = YES;
    }

当挂起队列的时候,正在执行的操作不受影响!
suspended : 决定队列的暂停和继续
operationCount : 队列中的操作数

2、取消所有操作

    NSLog(@"取消所有操作");
    //取消操作
    [self.opQueue cancelAllOperations];
    NSLog(@"取消之后的操作数 :%tu",self.opQueue.operationCount);

1.队列挂起的时候,不会清空内部的操作.只有在队列继续的时候才会清空!
2.正在执行的操作也不会被取消!

上面的代码就不贴打印结果验证了,结论我用文字写了。剩下的就留给你们自己去验证吧!!!(有错的话,请留言指出)

六、依赖关系

-(void)viewDidLoad{
    [super viewDidLoad];
    /*
     例子: 下载\解压\通知用户
     */
    //1.下载
    NSBlockOperation * op1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"下载---%@",[NSThread currentThread]);
    }];
    //2.解压
    NSBlockOperation * op2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"解压---%@",[NSThread currentThread]);
    }];
    //3.通知用户
    NSBlockOperation * op3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"通知用户---%@",[NSThread currentThread]);
    }];
    
    
    //NSOperation 提供了依赖关系
    //!!!! 注意,不要指定循环依赖,不然队列就不工作了!!
    [op2 addDependency:op1];
    [op3 addDependency:op2];
    //添加到队列中 waitUntilFinished:是否等待! YES,会卡住当前线程!!(不要在主线程中写YES,除非业务逻辑需要)
    [self.opQueue addOperations:@[op1,op2] waitUntilFinished:NO];
    //主线程通知用户
    [[NSOperationQueue mainQueue] addOperation:op3];
}

代码都给你们了,也写好了注释,因为NSOperation太简单易懂了,我想装逼多说一些都没办法,就这样吧。

多线程到这里就。。。。END!!!

有问题多多指出,我们一起进步!(点个关注呗!!!)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容