NSOPeration [NSOperationQueue addOperation]
NSOPeration:将“操作”添加到“队列”。GCD:将任务添加到队列。
NSOPeration抽象类 对GCD面向对象的封装,特点:不能直接使用 目的:定义子类共有的属性和方法.
子类:NSInvocationOperation、NSBlockOperation
NSThread -> pthread 队列:GCD 并发队列
NSOperation -> GCD 操作:异步执行任务
//NSOperation 和 GCD 对比: //GCD 在 iOS 4.0 推出,针对多核处理器优化的并发技术,是C语言的 -将任务(block)添加到队列 (串行、并行、主队列、全局队列),并且要指定任务的同步、异步; -线程间的通讯 dispatch_get_main_queue() -提供了一些 NSOperation 不具备的功能: 一次执行、 -延迟执行 、-调度组(NSoperation 也可以做到,但有点儿麻烦) // NSOperation 在 iOS 2.0; 苹果推出了GCD后,对NSOperation 进行了重写 -将操作[异步执行的任务添加到并发队列],就会立刻异步执行 -提供了一些 GCD实现起来比较麻烦的功能 【下载】 -最大并发数 -队列的暂停、继续 -取消所有线程 -线程依赖(线程A 的执行 必须依赖线程B)(GCD 同步实现!)
①NSInvocationOperation://将操作添加到队列
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downImage:) object:@"Invocation"]; //会在当前线程执行调度方法 //[op start];主线程 //队列 NSOperationQueue * q = [[NSOperationQueue alloc] init]; //将操作添加到队列--会自动异步执行调度方法 [q addOperation:op ];//downImage为子线程
②NSBlockOperation://将操作添加到队列
//1.队列 NSOperationQueue * q = [[NSOperationQueue alloc] init]; for (int i = 0; i<10; i++) { NSBlockOperation * op = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"---%@ -- %d",[NSThread currentThread],i);//执行顺序和开线程数不固定 }]; //操作添加到队列 [q addOperation:op]; } 简便方法: NSOperationQueue * q = [[NSOperationQueue alloc] init]; for (int i = 0; i<10; i++) { [q addOperationWithBlock:^{ NSLog(@"---%@ -- %d",[NSThread currentThread],i); }]; }
③全局队列
@property (nonatomic, strong) NSOperationQueue * opQueue ;//直接添加任务 for (int i = 0; i<10; i++) { [self.opQueue addOperationWithBlock:^{ NSLog(@"---%@ -- %d",[NSThread currentThread],i); }]; } //blockOperation NSBlockOperation * op1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"---BlockOperation%@ -- %d",[NSThread currentThread],100); }]; [self.opQueue addOperation:op1]; //invocation NSInvocationOperation * op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downImage:) object:@(101)]; [self.opQueue addOperation:op2];
④回归主线程
[self.opQueue addOperationWithBlock:^{ NSLog(@"%@",[NSThread currentThread]); //主线程 [[NSOperationQueue mainQueue] addOperationWithBlock:^{ NSLog(@"Main Thread %@",[NSThread currentThread]); }]; }];
⑤设置最大并发数(maxConcurrentOPerationCount)
//设置同时最大的并发操作数量 self.opQueue.maxConcurrentOperationCount = 2;//一次最多开两个 //线程的销毁原理 : A,B,C; 当A使用完之后,先把A回收到线程池,此时无法使用A,所以需要新开启一个线程 //20 文件? 20 线程? //Wifi : 5-6 //流量:2-3 for (int i = 0; i<20; i++) { [self.opQueue addOperationWithBlock:^{ [NSThread sleepForTimeInterval:1.0]; NSLog(@"---%@ -- %d",[NSThread currentThread],i); }]; }
⑥设置队列的暂停和继续(suspended)
//当挂起队列的时候,正在执行的操作是不被挂起!就绪状态的队列才会被挂起 //suspended : 决定队列的暂停和继续 operationCount: 队列中的操作数 - (IBAction)pause:(id)sender { //判断队列是否挂起 if (self.opQueue.isSuspended) { NSLog(@"继续 %tu",self.opQueue.operationCount); self.opQueue.suspended = NO; }else { NSLog(@"暂停 %tu",self.opQueue.operationCount); self.opQueue.suspended = YES; } }
⑦取消所有操作(cancelAllOperations)
- (IBAction)cancelAll:(id)sender { NSLog(@"取消所有操作!"); [self.opQueue cancelAllOperations];//此时点击 暂停、继续无法响应 :销毁所有任务 operationCount=0 //必须重新添加任务才可以使用暂停和继续 }
⑧提供依赖关系(addDependency)
- (void)dependency { /** * 下载、解压、通知用户 */ //1.下载 NSBlockOperation * op1 = [NSBlockOperation blockOperationWithBlock:^{ [NSThread sleepForTimeInterval:3.0]; NSLog(@"下载--%@ ",[NSThread currentThread]); }]; //2.解压 NSBlockOperation * op2 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"解压--%@ ",[NSThread currentThread]); }]; //3.通知用户 NSBlockOperation * op3 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"通知用户--%@ ",[NSThread currentThread]); }]; NSLog(@"Come here"); //NSOperation 提供依赖关系 [op2 addDependency:op1]; [op3 addDependency:op2]; //[op1 addDependency:op3];//循环依赖 此时队列不执行工作,也不会崩溃 //添加队列 [self.opQueue addOperations:@[op1,op2] waitUntilFinished:YES];// YES在所有任务都完成后才会走Come here. //在主线程上通知用户 [[NSOperationQueue mainQueue] addOperation:op3]; NSLog(@"Come here"); }