標籤:
2.NSOperation
(1)相關概念
01 NSOperation是對GCD的封裝02 兩個核心概念【隊列+操作】
(2)基本使用
01 NSOperation本身是抽象類別,只能只有它的子類02 三個子類分別是:NSBlockOperation、NSInvocationOperation以及自訂繼承自NSOperation的類03 NSOperation和NSOperationQueue結合使用實現多線程並發
(3)相關代碼
// 01 NSInvocationOperation //1.封裝操作 /* 第一個參數:目標對象 第二個參數:該操作要調用的方法,最多接受一個參數 第三個參數:調用方法傳遞的參數,如果方法不接受參數,那麼該值傳nil */ NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil]; //2.啟動操作 [operation start];------------------------------------------------- // 02 NSBlockOperation //1.封裝操作 /* NSBlockOperation提供了一個類方法,在該類方法中封裝操作 */ NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ //在主線程中執行 NSLog(@"---download1--%@",[NSThread currentThread]); }]; //2.追加操作,追加的操作在子線程中執行 [operation addExecutionBlock:^{ NSLog(@"---download2--%@",[NSThread currentThread]); }]; [operation addExecutionBlock:^{ NSLog(@"---download3--%@",[NSThread currentThread]); }]; //3.啟動執行操作 [operation start];----------------------------------------------// 03 自訂NSOperation //如何封裝操作? //自訂的NSOperation,通過重寫內部的main方法實現封裝操作 -(void)main { NSLog(@"--main--%@",[NSThread currentThread]); } //如何使用? //1.執行個體化一個自訂動作對象 XLOperation *op = [[XLOperation alloc]init]; //2.執行操作 [op start];
(1)NSOperation中的兩種隊列
01 主隊列 通過mainQueue獲得,凡是放到主隊列中的任務都將在主線程執行02 非主隊列 直接alloc init出來的隊列。非主隊列同時具備了並發和串列的功能,通過設定最大並發數屬性來控制任務是並發執行還是串列執行
(2)相關代碼
//自訂NSOperation-(void)customOperation{ //1.建立隊列 NSOperationQueue *queue = [[NSOperationQueue alloc]init]; //2.封裝操作 //好處:1.資訊隱蔽 //2.代碼複用 XLOperation *op1 = [[XLOperation alloc]init]; XLOperation *op2 = [[XLOperation alloc]init]; //3.添加操作到隊列中 [queue addOperation:op1]; [queue addOperation:op2];}//NSBlockOperation- (void)blockOperation{ //1.建立隊列 /* 並發:全域並發隊列,自己建立(concurrent) 串列:主隊列,自己建立(serial) */ // NSOperationQueue /* 主隊列:凡是放到主隊列裡面的任務都在主線程執行[NSOperationQueue mainQueue] 非主隊列:alloc int,同時具備了並發和串列的功能,預設是並發隊列 */ NSOperationQueue *queue = [[NSOperationQueue alloc]init]; //2.封裝操作 NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"1----%@",[NSThread currentThread]); }]; NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"2----%@",[NSThread currentThread]); }]; [op2 addExecutionBlock:^{ NSLog(@"3----%@",[NSThread currentThread]); }]; [op2 addExecutionBlock:^{ NSLog(@"4----%@",[NSThread currentThread]); }]; //3.添加操作到隊列中 [queue addOperation:op1]; [queue addOperation:op2]; [queue addOperation:op3]; //補充:簡便方法 [queue addOperationWithBlock:^{ NSLog(@"5----%@",[NSThread currentThread]); }];}//NSInvocationOperation- (void)invocation{ /* GCD中的隊列: 串列隊列:自己建立的(serial),主隊列 並發隊列:自己建立的(concurrent),全域並發隊列 NSOperationQueue 主隊列:[NSOperationQueue mainqueue];凡事放在主隊列中的操作都在主線程中執行 非主隊列:[[NSOperationQueue alloc]init],並發和串列,預設是並發執行的 */ //1.建立隊列 NSOperationQueue *queue = [[NSOperationQueue alloc]init]; //2.封裝操作 NSInvocationOperation *op1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download1) object:nil]; NSInvocationOperation *op2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download2) object:nil]; NSInvocationOperation *op3 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download3) object:nil]; //3.把封裝好的操作添加到隊列中 [queue addOperation:op1];//[op1 start] [queue addOperation:op2]; [queue addOperation:op3];}
(1)設定最大並發數【控制任務並發和串列】
//1.建立隊列 NSOperationQueue *queue = [[NSOperationQueue alloc]init]; //2.設定最大並發數 //注意點:該屬性需要在任務添加到隊列中之前進行設定 //該屬性控制隊列是串列執行還是並發執行 //如果最大並發數等於1,那麼該隊列是串列的,如果大於1那麼是並行的 //系統的最大並發數有個預設的值,為-1,如果該屬性設定為0,那麼不會執行任何任務 queue.maxConcurrentOperationCount = 2;
(2)暫停和恢複以及取消
//設定暫停和恢複 //suspended設定為YES表示暫停,suspended設定為NO表示恢複 //暫停表示不繼續執行隊列中的下一個任務,暫停操作是可以恢複的 if (self.queue.isSuspended) { self.queue.suspended = NO; }else{ self.queue.suspended = YES; } //取消隊列裡面的所有操作 //取消之後,當前正在執行的操作的下一個操作將不再執行,而且永遠都不在執行,就像後面的所有任務都從隊列裡面移除了一樣 //取消操作是不可以恢複的 [self.queue cancelAllOperations];---------自訂NSOperation取消操作---------------------------(void)main{ //耗時操作1 for (int i = 0; i<1000; i++) { NSLog(@"任務1-%d--%@",i,[NSThread currentThread]); } NSLog(@"+++++++++++++++++++++++++++++++++"); //蘋果官方建議,每當執行完一次耗時操作之後,就查看一下當前隊列是否為取消狀態,如果是,那麼就直接退出 //好處是可以提高程式的效能 if (self.isCancelled) { return; } //耗時操作2 for (int i = 0; i<1000; i++) { NSLog(@"任務1-%d--%@",i,[NSThread currentThread]); } NSLog(@"+++++++++++++++++++++++++++++++++");}
- 2.4 NSOperation 操作依賴和監聽
//1.建立隊列 NSOperationQueue *queue = [[NSOperationQueue alloc]init]; NSOperationQueue *queue1 = [[NSOperationQueue alloc]init]; //2.封裝操作 NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"1----%@",[NSThread currentThread]); }]; NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"2----%@",[NSThread currentThread]); }]; NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"3----%@",[NSThread currentThread]); }]; NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"4----%@",[NSThread currentThread]); }]; NSBlockOperation *op5 = [NSBlockOperation blockOperationWithBlock:^{ for (NSInteger i=0; i<10000; i++) { NSLog(@"5-%zd---%@",i,[NSThread currentThread]); } }]; // 監聽完成 op4.completionBlock = ^{ NSLog(@"op4已經完成了---%@",[NSThread currentThread]); }; //添加操作依賴,注意不能循環相依性 [op1 addDependency:op5]; [op1 addDependency:op4]; //添加操作到隊列 [queue addOperation:op1]; [queue addOperation:op2]; [queue addOperation:op3]; [queue addOperation:op4]; [queue1 addOperation:op5];
(2)下載多張圖片合成綜合案例(設定作業依賴)
//02 綜合案例- (void)download2{ NSLog(@"----"); //1.建立隊列 NSOperationQueue *queue = [[NSOperationQueue alloc]init]; //2.封裝操作下載圖片1 NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{ NSURL *url = [NSURL URLWithString:@"http://h.hiphotos.baidu.com/zhidao/pic/item/6a63f6246b600c3320b14bb3184c510fd8f9a185.jpg"]; NSData *data = [NSData dataWithContentsOfURL:url]; //拿到圖片資料 self.image1 = [UIImage imageWithData:data]; }]; //3.封裝操作下載圖片2 NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{ NSURL *url = [NSURL URLWithString:@"http://pic.58pic.com/58pic/13/87/82/27Q58PICYje_1024.jpg"]; NSData *data = [NSData dataWithContentsOfURL:url]; //拿到圖片資料 self.image2 = [UIImage imageWithData:data]; }]; //4.合成圖片 NSBlockOperation *combine = [NSBlockOperation blockOperationWithBlock:^{ //4.1 開啟圖形上下文 UIGraphicsBeginImageContext(CGSizeMake(200, 200)); //4.2 畫image1 [self.image1 drawInRect:CGRectMake(0, 0, 200, 100)]; //4.3 畫image2 [self.image2 drawInRect:CGRectMake(0, 100, 200, 100)]; //4.4 根據圖形上下文拿到圖片資料 UIImage *image = UIGraphicsGetImageFromCurrentImageContext();// NSLog(@"%@",image); //4.5 關閉圖形上下文 UIGraphicsEndImageContext(); //7.回到主線程重新整理UI [[NSOperationQueue mainQueue]addOperationWithBlock:^{ self.imageView.image = image; NSLog(@"重新整理UI---%@",[NSThread currentThread]); }]; }]; //5.設定作業依賴 [combine addDependency:op1]; [combine addDependency:op2]; //6.添加操作到隊列中執行 [queue addOperation:op1]; [queue addOperation:op2]; [queue addOperation:combine]; }
iOS 多線程(4)NSOperation