天天看點

NSThread,NSInvocationOperation,NSBlockOperation,GCD解析

iOS有三種多線程程式設計的技術,分别是:

(一) NSThread

(二)Cocoa NSOperation

(三)GCD(全稱:Grand Central Dispatch)

  這三種程式設計方式從上到下,抽象度層次是從低到高的,抽象度越高的使用越簡單,也是Apple最推薦使用的。

三種方式介紹:

1)NSThread

      在處理機制上,需要開發者負責手動管理Thread的生命周期,包括子線程與主線程之間的同步等。線程共享同一應用程式的部分記憶體空間,它們擁有對資料相同的通路權限。你得協調多個線程對同一資料的通路,一般做法是在通路之前加鎖,這會導緻一定的性能開銷。

2)NSOperation

      可以認為NSOperationQueue就是一個線程管理器,通過addOperation方法,我們可以一次性把多個線程添加到隊列中。同時,NSOperationQueue允許通過setMaxConcurrentOperationCount方法設定隊列并行執行的線程數量。

3)GCD

      GCD是Apple開發的一個多核程式設計的解決方法。該方法在Mac OS X 10.6雪豹中首次推出,并随後被引入到了iOS4.0中。GCD是一個替代諸如NSThread,NSOperationQueue,NSInvocationOperation等技術的很高效和強大的技術。

三種方式的優缺點介紹:

1)NSThread:

優點:NSThread 比其他兩個輕量級

缺點:需要自己管理線程的生命周期,線程同步。線程同步對資料的枷鎖會有一定的系統開銷。

2)Cocoa NSOperation

優點:不需要關心線程管理,資料同步的事情,可以把精力放在自己需要執行的操作上。

Cocoa operation相關的類是 NSOperation, NSOperationQueue.

              NSOperation是個抽象類,使用它必須使用它的子類,可以實作它或者使用它定義好的兩個子類:NSInvocationOperation 和 NSBlockOperation.

              NSOperationQueue是線程隊列,裡面存放需要執行的線程。  建立NSOperation子類的對象,把對象添加到NSOperationQueue隊列裡執行。

3)GCD

優點:GCD比之thread更簡單易用。并且處理效率很高。GCD自動根據系統負載來增減線程數量,這就減少了上下文切換以及增加了計算效率。

三種方法的方法介紹:

1)NSThread:

建立方式主要有兩種:

[NSThread detachNewThreadSelector:@selector(myThreadMainMethod:) toTarget:self withObject:nil];

NSThread* myThread = [[NSThread alloc] initWithTarget:self

selector:@selector(myThreadMainMethod:)

object:nil];

[myThread start]; //啟動線程

這兩種方式的差別是:前一種一調用就會立即建立一個線程來做事情;而後一種雖然你 alloc 了也 init了,但是要直到我們手動調用 start 啟動線程時才會真正去建立線程。這種延遲實作思想在很多跟資源相關的地方都有用到。後一種方式我們還可以在啟動線程之前,對線程進行配置,比如設定 stack 大小,線程優先級。

此外還有一種間接的方式:利用NSObject的方法

performSelectorInBackground:withObject: 來建立一個線程:

[myObj performSelectorInBackground:@selector(myThreadMainMethod) withObject:nil]; //在背景運作某一個方法

其效果與 NSThread 的 detachNewThreadSelector:toTarget:withObject: 是一樣的。

2)NSOperationQueue:

1> 使用步驟:

    1) 執行個體化操作

      _queue = [[NSOperationQueue alloc] init];

     a) NSInvocationOperation

       NSInvocationQperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(opAction) object:nil];

      // 如果使用start,會在目前線程啟動操作

       [op1 start];

      //一旦将操作添加到操作隊列,操作就會啟動

       [_queue addOperation:op1];

       b) NSBlockOperation

       #pragma mark  -模仿下載下傳網絡圖像

       - (IBAction)operationDemo3:(id)sender

       {

         //1.下載下傳

          NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{

                NSLog(@"下載下傳%@",[NSThread currendThread]);

         }];

         // 2.濾鏡

        NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{

             NSLog(@"下載下傳%@",[NSThread currendThread]);

       }];

           //3.顯示

          NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{

               NSLog(@"更新UI%@",[NSThread currendThread]);

           }];

          //添加操作之間的依賴關系,所謂“依賴”關系,就是等待前一個任務完成後,後一個任務才能啟動

          //依賴關系可以跨線程隊列實作

         //提示:在指定依賴關系時,注意不要循環依賴,否則不工作。

         [op2 addDepandency:op1];

         [op3 addDependency:op2];

         [_queue addOperation:op1];

         [_queue addOperation:op2]; 

         [[NSOperationQueue mainQueue] addOperation:op3];

       }

    2) 将操作添加到隊列NSOperationQueue即可啟動多線程執行

         [_queue addOperation:op1];

         [_queue addOperation:op2];

 2> 更新UI使用主線程隊列

        //兩方式

        [[NSOperationQueue mainQueue] addOperation:^{

          [[NSOperationQueue mainQueue] addOperation:op3];

        }];

 3> 操作隊列的setMaxConcurrentOperationCount

    可以設定同時并發的線程數量!

   [_queue setMacConcurrentOperationCount:2];

    提示:此功能僅有NSOperation有!

 4> 使用addDependency可以設定任務的執行先後順序,同時可以跨操作隊列指定依賴關系

   [op2 addDependency:op1];

      [op3 addDependency:op2];

      [op1 addDepandency:op3];

    提示:在指定依賴關系時,注意不要循環依賴,否則不工作。