1.NSOperation总结
NSOperaton 是苹果大力推荐的"并发"技术!
NSOperation 的核心概念:将"操作" 添加到 "队列"
GCD 将"任务"添加到 "队列"
NSOperation 类 是一个抽象类
特点:
-不能直接使用!
目的:
-定义子类共有的属性和方法
子类:
NSInvocationOperation
NSBlockOperation
自定义子类继承NSOperation,实现内部相应的方法
GCD & NSOperation 对比
GCD 在 iOS 4.0 推出,主要针对多核处理器做了优化的并发技术,是C语言的
- 将"任务"[block]添加到 队列[串行/并发/主队列/全局队列] ,并且指定执行任务的函数[同步/异步]
- 线程间的通讯 dispatch_get_main_queue()
- 提供了一些 NSOperation 不具备的功能
- 一次执行
- 延迟执行
- 调度组(在op中也可以做到,有点麻烦)
NSOperation 在 iOS 2.0 推出的,苹果推出 GCD以后,对NSOperation 底层做了重写!
- 将操作[异步执行的任务] 添加到队列[并发队列],就会立刻异步执行
- 线程间的通讯 mainQueue
- 提供了一些GCD 实现起来比较困难的功能
- 最大并发线程
- 队列的暂停/继续
- 取消所有操作
- 指定操作之间的依赖关系(GCD 用同步来实现)
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
网友评论