多執行緒程式設計-003-NSOPeration
阿新 • • 發佈:2018-11-14
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"); }