NSOperation的使用

2018-02-05  本文已影响7人  CoderLWG

1.NSOperation总结

NSOperaton 是苹果大力推荐的"并发"技术!
NSOperation 的核心概念:将"操作" 添加到 "队列"
GCD 将"任务"添加到 "队列"
NSOperation 类 是一个抽象类
特点:
-不能直接使用!
目的:
-定义子类共有的属性和方法
子类:
NSInvocationOperation
NSBlockOperation
自定义子类继承NSOperation,实现内部相应的方法


GCD & NSOperation 对比
GCD 在 iOS 4.0 推出,主要针对多核处理器做了优化的并发技术,是C语言的


NSOperation 在 iOS 2.0 推出的,苹果推出 GCD以后,对NSOperation 底层做了重写!

2.NSInvocationOperation使用

/*
开启多个线程  不会顺序执行
 NSOperation 本质上是对 GCD  的面向对象的封装!
 - 队列:本质上 就是GCD的并发队列
 - 操作:异步执行任务

*/
//1.队列
    NSOperationQueue * q = [[NSOperationQueue alloc]init];
    for (int i = 0; i < 10; i++) {
         NSInvocationOperation * op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadImage:) object:@(i)];
        
        //将操作添加到队列 - 会自动异步执行调度方法
        [q addOperation:op];
    }
image.png

3.NSBlockOperation使用

//NSBlockOperation 所有代码都写在一起,便于维护
//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];
    }
// 更简单的一种方式,直接通过队列添加操作
//1.队列 - > 队列如果每次分配会比较浪费
    //在实际开发中,会使用全局队列
    NSOperationQueue * q = [[NSOperationQueue alloc]init];
    //2.添加操作
    for (int i = 0; i < 10; i++) {
        [q addOperationWithBlock:^{
            NSLog(@"%@ --- %d",[NSThread currentThread],i);
        }];
    }

4.全局队列

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

-(void)demo{
 //直接添加任务
    for (int i = 0; i < 10; i++) {
        [self.opQueue addOperationWithBlock:^{
            NSLog(@"%@ --- %d",[NSThread currentThread],i);
        }];
    }
    
    //block operation
    NSBlockOperation * op1 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"BLOCK %@ --- %d",[NSThread currentThread],100);
    }];
    [self.opQueue addOperation:op1];
    
    //invocation operation
    NSInvocationOperation * op2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downloadImage:) object:@"invocation"];
    [self.opQueue addOperation:op2];
}

5.线程间的通信

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

6.设置最大并发数

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

可以看出,maxConcurrentOperationCount不设置的时候,最大并发数有22个
-(void)demo{
   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

7.队列的取消、暂停、恢复

取消队列的所有操作
- (void)cancelAllOperations;
提示:也可以调用NSOperation的- (void)cancel方法取消单个操作

暂停和恢复队列
- (void)setSuspended:(BOOL)b; // YES代表暂停队列,NO代表恢复队列
- (BOOL)isSuspended;

8.操作依赖

NSOperation之间可以设置依赖来保证执行顺序
比如一定要让操作A执行完后,才能执行操作B,可以这么写
[operationB addDependency:operationA]; // 操作B依赖于操作A
可以在不同queue的NSOperation之间创建依赖关系
注意:不能相互依赖
比如A依赖B,B依赖A
上一篇 下一篇

猜你喜欢

热点阅读