NSOperation的介紹


iOS開發多線程篇—NSOperation簡單介紹

一、NSOperation簡介
1. 簡單說明
a. NSOperation的作用:
是OC語言中基於GCD的面向對象的封裝,使用起來比GCD更加簡單(面向對象);
提供了一些用GCD不好實現的功能,使用NSOperation不用關心線程以及線程的生命週期(蘋果推薦使用)。

b. 配合使用NSOperation和NSOperationQueue實現多線程編程的具體步驟:

(1)先將需要執行的操作封裝到一個NSOperation對象中

(2)然後將NSOperation對象添加到NSOperationQueue中

(3)系統會⾃動將NSOperationQueue中的NSOperation取出來

(4)將取出的NSOperation封裝的操作放到⼀條新線程中執⾏

c. NSOperation的子類

NSOperation是一個抽象類,不能直接使用(方法沒有實現),約束子類都具有共同的屬性和方法,並不具備封裝操作的能力,必須使⽤它的子類。
使用NSOperation⼦類的方式有3種:
(1)NSInvocationOperation
(2)NSBlockOperation
(3)自定義子類繼承NSOperation,實現內部相應的⽅法

2. 具體說明
2.1 NSInvocationOperation子類不常用
創建對象和執行操作:
 //創建操作對象,封裝要執行的任務
 //NSInvocationOperation 封裝操作
  NSInvocationOperation *operation=[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(test) object:nil];
//執行操作
   [operation start];

注意:操作對象默認在主線程中執行,只有添加到隊列中才會開啓新的線程。即默認情況下,如果操作沒有放到隊列中queue中,都是同步執行。只有將NSOperation放到一個NSOperationQueue中,纔會異步執行操作,不常用!

2.2 NSBlockOperation子類
注意:只要NSBlockOperation封裝的操作數 > 1,就會異步執行操作。
創建對象和添加操作:
//創建NSBlockOperation操作對象
  NSBlockOperation *operation=[NSBlockOperation blockOperationWithBlock:^{
      NSLog(@"NSBlockOperation1------%@",[NSThread currentThread]);
           }];
 //通過addExecutionBlock:方法添加更多的操作
 [operation addExecutionBlock:^{
     NSLog(@"NSBlockOperation2------%@",[NSThread currentThread]);
           }];
[operation start];
打印結果:
2015-10-26 14:06:11.765 test1[7036:326837] NSBlockOperation1------<NSThread: 0x7f8628e074d0>{number = 1, name = main}
2015-10-26 14:06:11.767 test1[7036:326882] NSBlockOperation2------<NSThread: 0x7f8628e2ef10>{number = 2, name = (null)}

2.3 NSOperationQueue
NSOperation可以調⽤start⽅法來執⾏任務,但默認是同步執行的。
如果將NSOperation添加到NSOperationQueue(操作隊列)中,系統會自動異步執行NSOperation中的操作。
也就是說添加操作到NSOperationQueue中,自動執行操作,自動開啓線程。

添加操作到NSOperationQueue中的兩種那個方法:
 - (void)addOperation:(NSOperation *)op;
- (void)addOperationWithBlock:(void (^)(void))block;

注意:系統自動將NSOperationqueue中的NSOperation對象取出,將其封裝的操作放到一條新的線程中執行,這些任務是並行執行的。
提示:隊列的取出是有順序的,與打印結果並不矛盾。這就好比,選手A,B,C雖然起跑的順序是先A,後B,然後C,但是到達終點的順序卻不一定是A,B在前,C在後。

下面使用for循環打印,可以更明顯的看出任務是併發執行的。
代碼示例:
//創建NSInvocationOperation對象,封裝操作
   
NSInvocationOperation *operation1=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(test1) object:nil];
   
NSInvocationOperation *operation2=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(test2) object:nil];
   
//創建NSBlockOperation對象,封裝操作
   
NSBlockOperation *operation3=[NSBlockOperation blockOperationWithBlock:^{
       
for (int i=0; i<5; i++) {
           
NSLog(@"NSBlockOperation3--1----%@",[NSThread currentThread]);
        }
    }];
    [operation3
addExecutionBlock:^{
       
for (int i=0; i<5; i++) {
           
NSLog(@"NSBlockOperation3--2----%@",[NSThread currentThread]);
        }
    }];
   
//創建NSOperationQueue
   
NSOperationQueue * queue=[[NSOperationQueue alloc]init];
   
//把操作添加到隊列中
    [queue
addOperation:operation1];
    [queue
addOperation:operation2];
    [queue
addOperation:operation3];
}
-(void)test1
{
   
for (int i=0; i<5; i++) {
       
NSLog(@"NSInvocationOperation1--%@",[NSThread currentThread]);
    }
}
-(void)test2
{
   
for (int i=0; i<5; i++) {
       
NSLog(@"NSInvocationOperation2--%@",[NSThread currentThread]);
    }
}
打印結果:

二、NSOperation 和 GCD 的比較
1. GCD
a.     GCD是iOS4.0 推出的,主要針對多核cpu做了優化,是C語言的技術;
b.     GCD是將任務(block)添加到隊列(串行/並行/全局/主隊列),並且以同步/異步的方式執行任務的函數;
c.     GCD提供了一些NSOperation不具備的功能
     1)一次性執行
     2)延遲執行
     3)調度組

2.  NSOperation
a.     NSOperation是iOS2.0推出的,iOS4之後重寫了NSOperation;
b.     NSOperation將操作(異步的任務)添加到隊列(併發隊列),就會執行指定的操作;
c.     NSOperation裏提供了方便的操作:
1)最大併發數:同時執行的任務數。
比如,同時開3個線程執行3個任務,併發數就是3。
最大併發數的相關方法
- (NSInteger)maxConcurrentOperationCount;
- (void)setMaxConcurrentOperationCount:(NSInteger)cnt;
示例:
-(NSOperationQueue *)queue {
   
if(!_queue){
       
_queue =[[NSOperationQueue alloc] init];
        //設置對大併發數
        _queue.maxConcurrentOperationCount = 3;
    }
   
return _queue;
}
2)隊列的暫定/繼續,
// YES代表暫停隊列,NO代表恢復隊列。
- (void)setSuspended:(BOOL)b; 
- (BOOL)isSuspended;
3)取消隊列的所有操作
- (void)cancelAllOperations;
提示:也可以調用NSOperation的- (void)cancel方法取消單個操作。
示例:
//暫停暫停的是隊列中還沒有被運行的操作,正在運行的操作不能被暫停;
//當隊列爲暫停的時候,往隊列中加入操作,也不會運行。
- (IBAction)pauseClick:(id)sender {
   
NSLog(@"點擊暫停");
    [
self.queue setSuspended:YES];
}
//繼續
- (
IBAction)resumeClick:(id)sender {
   
NSLog(@"點擊繼續");
    [
self.queue setSuspended:NO];
}
//取消
- (
IBAction)cancelClick:(id)sender {
   
NSLog(@"點擊取消");
    [
self.queue cancelAllOperations];
}
4)指定操作之間的依賴關係(GCD可以用同步實現)
a. NSOperation之間可以設置依賴來保證執行順序,比如一定要讓操作A執行完後,才能執行操作B,可以這麼寫:
// 操作B依賴於操作A
[operationB addDependency:operationA]; 
b. 可以在不同queue的NSOperation之間創建依賴關係。
c. 注意不能相互依賴,比如A依賴B,B依賴A。
示例:
-(void)demo{
    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
       
//模擬耗時操作
        [
NSThread sleepForTimeInterval:arc4random_uniform(3)];
       
NSLog(@"1.登陸 %@",[NSThread currentThread]);
    }];
    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        [
NSThread sleepForTimeInterval:arc4random_uniform(3)];
       
NSLog(@"2.扣費 %@",[NSThread currentThread]);
    }];
    NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        [
NSThread sleepForTimeInterval:arc4random_uniform(3)];
       
NSLog(@"3.下載 %@",[NSThread currentThread]);
    }];
    NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
       
NSLog(@"4.UI更新 %@",[NSThread currentThread]);
    }];
    //添加操作依賴,要在操作放到隊列之前。
   
//操作依賴可以跨隊列設置。
    [op2
addDependency:op1];
    [op3
addDependency:op2];
    [op4 addDependency:op3];
    [self.queue addOperations:@[op1,op2,op3] waitUntilFinished:NO];
    [[
NSOperationQueue mainQueue] addOperation:op4];
}
5)操作隊列的優先級
設置NSOperation在queue中的優先級,可以改變操作的執行優先級。
操作的優先級,優先級高的操作不一定最先運行。
隊列的優先級 ,優先級高的隊列不一定比優先級低的隊列先運行完,而是有更多的可能被執行到。

6)線程間通信:
子線程->主線程 
操作方式與GCD類似。
示例:
[self.queue addOperationWithBlock:^{
         //子線程:do something
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
         //主線程的任務,操作UI等
    }];
}];

此外:
有些操作任務如果在主線程完成,會嚴重的影響到用戶體驗,造成UI卡的現象。我們可以通過自定義NSOperation,新開線程,讓加載圖片的任務異步執行,來解決此問題。








發佈了53 篇原創文章 · 獲贊 5 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章