本质上是GCD的并发队列异步执行,是对GCD的面向对象的封装,是苹果大力推荐的并发技术
与GCD的对比:
- GCD:
- iOS 4.0 推出
- 针对多核处理器做了优化的并发技术
- 是C语言
- 提供一次执行、延迟执行、调度组
- 将任务添加到队列(串行、并发、主队列、全局队列),并且指定执行任务的函数(同步、异步)
- NSOperation:
- iOS 2.0 推出
- 底层是GCD
- 面向对象
- 提供最大并发线程、队列暂停继续、取消所有操作、指定操作之间的依赖关系
- 将操作添加到队列(并发),然后立即异步执行
NSOperation 是一个抽象类,继承NSObject
- 特点:不能直接使用
- 目的:定义子类共有属性和方法
- 子类:
- NSInvocationOperation
- NSBlockOperation
1 2 3 4 5 6 7 8 9 10 11 12
| - (void)demo1 { NSInvocationOperation * op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadImage:) object:@"invocation"]; [op start]; } - (void)downloadImage:(id)objc { NSLog(@"%@ %@", [NSThread currentThread, objc]); }
- (void)viewDidLoad { [super viewDidLoad]; [self demo1]; }
|
使用队列
1 2 3 4 5 6
| - (void)demo1 { NSInvocationOperation * op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadImage:) object:@"invocation"]; NSOperationQueue * q =[[NSOperationQueue alloc] init]; // 添加到队列 [q addOperation: op] }
|
NSBlockOperation
1 2 3 4 5 6
| - (void)demo3 { NSOperationQueue * q =[[NSOperationQueue alloc] init]; NSBlockOperation * op = [NSBlockOperation blockOperationWithBlock: ^{ NSLog(@"%@", [NSThread currentThread]); }] }
|
更简单的写法
1 2 3 4 5 6
| - (void)demo4 { NSOperationQueue * q =[[NSOperationQueue alloc] init]; [q addOperationWithBlock: ^{ NSLog(@"%@", [NSThread currentThread]); }] }
|
使用全局队列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| @interface ViewController() // 先定义一个全局变量,然后用它指向一个队列 @property(nonacomic, strong) NSOperationQueue * opQueue; @end
@implementation ViewController
// 懒加载 -(NSOperationQueue *)opQueue { if(!_opQueue) { _opQueue = [[NSOperationQueue alloc]init]; } return _opQueue; }
// 使用 - (void)demo5 { [self.opQueue addOperationWithBlock: ^{ NSLog(@"%@", [NSThread currentNSThread]); }]; // block operation NSBlockOperation * op1 = [NSBlockOperation blockOperationWithBlock: ^{ NSLog(@"%@", [NSThread currentThread]); }]; [self.opQueue addOperation: op1]; // invocation operation NSInvocationOperation * op2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downloadImage:) object:@"invocation"]; [self.opQueue addOperation: op2]; }
@end
|
线程间的通讯,在子线程更新UI
1 2 3 4 5 6 7 8 9
| - (void)demo6 { [self.opQueue addOperationWithBlock: ^{ NSLog(@"耗时操作 %@", [NSThread currentThread]); // 主线程更新UI,首先拿到主线程 [[NSOperationQueue mainQueue] AddOperationWithBlock: ^{ NSLog(@"UI操作 %@", [NSThread currentThread]); }]; }]; }
|
最大并发数,iOS 8.0 开始无论使用GCD还是NSOperation都会开启很多子线程,iOS 7.0 以前,GCD通常只会开启5~6条线程
一般情况下,WIFI网络设置5、6,流量网络设置2、3
1 2 3 4 5 6 7 8 9
| - (void)demo7 { // 控制最大线程数量 self.opQueue.maxConcurrentOperationCount = 2; for(int i = 0; i < 20; i++) { [self.opQueue addOperationWithBlock: ^{ NSLog(@"%@", [NSThread currentThread]); }]; } }
|
暂停、继续
1 2 3 4 5 6 7 8 9 10
| -(IBAction) pause { // 判断队列是否挂起(暂停) if(self.opQueue.isSuspended) { NSLog(@"继续"); self.opQueue.suspended = NO; } else { NSLog(@"暂停"); self.opQueue.suspended = YES; } }
|
取消所有操作
1 2 3 4
| - (IBAction) cancelAll { NSLog(@"取消所有操作"); [self.opQueue cancelAllOperations]; }
|
依赖关系
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| - (void) dependecy { NSBlockOperation * op1 = [NSBlockOperation blockOperationWithBlock: ^{ NSLog(@"动作 1 %@", [NSThread currentThread]); }]; NSBlockOperation * op2 = [NSBlockOperation blockOperationWithBlock: ^{ NSLog(@"动作 2 %@", [NSThread currentThread]); }]; NSBlockOperation * op3 = [NSBlockOperation blockOperationWithBlock: ^{ NSLog(@"动作 3 %@", [NSThread currentThread]); }]; // NSOperation 的依赖关系,op2依赖于op1,op3依赖于op2 [op2 addDependency: op1]; [op3 addDependency: op2]; // 添加到队列,waitUntilFinished是“是否等待”,会卡住当前线程 [self.opQueue addOperations:@[op1, op2, op3] waitUntilFinished:YES]; // 更新UI让主线程执行操作 [[NSOperationQueue mainQueue] addOperation:op3]; NSLog(@"运行至此"); }
|