開始 GCD

GCD的第一次接觸

  • 上一篇文章,從這里開始學習GCD。

GCD的使用
-- 摘自唐巧的技術博客

GCD之dispatch queue深入淺出

  • 為了方便地使用GCD,蘋果提供了一些方法方便我們將block放在主線程 或 后臺線程執行,或者延后執行。

      //  后臺執行:
      dispatch_async(dispatch_get_global_queue(0, 0), ^{
          // something
      });
      
      // 主線程執行:
      dispatch_async(dispatch_get_main_queue(), ^{
          // something
      });
      
      // 一次性執行:
      static dispatch_once_t onceToken;
      dispatch_once(&onceToken, ^{
          // code to be executed once
      });
      
      // 延遲2秒執行:
      double delayInSeconds = 2.0;
      dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds *NSEC_PER_SEC);
      dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
          // code to be executed on the main queue after delay
      });
    
  • GCD中有三種隊列類型:

    • The main queue:

        與主線程功能相同。實際上,提交至main queue的任務會在主線程中執行。main queue可以調用dispatch_get_main_queue()來獲得。因為main queue是與主線程相關的,所以這是一個串行隊列。
      
    • Global queues:

        全局隊列是并發隊列,并由整個進程共享。進程中存在三個全局隊列:高、中(默認)、低三個優先級隊列。可以調用dispatch_get_global_queue函數傳入優先級來訪問隊列。
      
    • 用戶隊列:

        用戶隊列 (GCD并不這樣稱呼這種隊列, 但是沒有一個特定的名字來形容這種隊列,所以我們稱其為用戶隊列) 是用函數 dispatch_queue_create 創建的隊列. 這些隊列是串行的。正因為如此,它們可以用來完成同步機制, 有點像傳統線程中的mutex。
      
  • dispatch_async:

    將任務進行異步并行處理,不一定需要一個任務處理完后才能處理下一個。

  • dispatch queue分為下面兩種:

    而系統默認就有一個串行隊列main_queue和并行隊列global_queue:

      Serial Dispatch Queue -- 線程池只提供一個線程用來執行任務,所以后一個任務必須等到前一個任務執行結束才能開始。
      
      Concurrent Dispatch Queue -- 線程池提供多個線程來執行任務,所以可以按序啟動多個任務并發執行。
    

而系統默認就有一個串行隊列main_queue和并行隊列global_queue:

  • dispatch_get_main_queue() 函數:

    就是返回主線程,^{} 封裝的就是任務代碼,這樣嵌套方式就可以從一個隊列queue,跳到另一個queue

  • dispatch_get_global_queue(dispatch_queue_priority_t priority,
    unsigned long flags):

    會獲取一個全局隊列,我們姑且理解為系統為我們開啟的一些全局線程。

    dispatch_queue_priority_t priority: 隊列中近程的優先級。

    unsigned long flags: flag作為保留字段備用(一般為0)

  • dispatch_group_async的使用

    dispatch_group_async可以實現監聽一組任務是否完成,完成后得到通知執行其他的操作。這個方法很有用,比如你執行三個下載任務,當三個任務都下載完成后你才通知界面說完成的了。下面是一段例子代碼:

    - (IBAction)touchUpInsideByThreadOne:(id)sender 
    {  
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);  
        dispatch_group_t group = dispatch_group_create();  
        dispatch_group_async(group, queue, ^{  
            [NSThread sleepForTimeInterval:6];  
            NSLog(@"group1 [NSThread sleepForTimeInterval:6];");  
        });  
        dispatch_group_async(group, queue, ^{  
            [NSThread sleepForTimeInterval:3];  
            NSLog(@"group2 [NSThread sleepForTimeInterval:3];");  
        });  
        dispatch_group_async(group, queue, ^{  
            [NSThread sleepForTimeInterval:1];  
            NSLog(@"group3 [NSThread sleepForTimeInterval:1];");  
        });  
        dispatch_group_notify(group, dispatch_get_main_queue(), ^{  
            NSLog(@"main thread.");  
        });  
        dispatch_release(group);  
    } 
    
  • dispatch_barrier_async的使用

    dispatch_barrier_async是在前面的任務執行結束后它才執行,而且它后面的任務等它執行完成之后才會執行

    - (IBAction)touchUpInsideByThreadOne:(id)sender
    {
        dispatch_queue_t queue = dispatch_queue_create("gcdtest.rongfzh.yc", DISPATCH_QUEUE_CONCURRENT);
    
        dispatch_async(queue, ^{
            [NSThread sleepForTimeInterval:3];
            NSLog(@"dispatch_async1");
        });
        dispatch_async(queue, ^{
            [NSThread sleepForTimeInterval:1];
            NSLog(@"dispatch_async2");
        });
        dispatch_barrier_async(queue, ^{
            NSLog(@"dispatch_barrier_async");
            [NSThread sleepForTimeInterval:0.5];
        
        });
        dispatch_async(queue, ^{
            [NSThread sleepForTimeInterval:1];
            NSLog(@"dispatch_async3");
        });
    }
    

    執行結果為:

    2013-07-24 17:01:54.580 NSThreadAndBlockDemo[2153:12b03] dispatch_async2  
    2013-07-24 17:01:56.580 NSThreadAndBlockDemo[2153:12303] dispatch_async1  
    2013-07-24 17:01:56.580 NSThreadAndBlockDemo[2153:12303] dispatch_barrier_async  
    2013-07-24 17:01:58.083 NSThreadAndBlockDemo[2153:12303] dispatch_async3 
    

    如果使用dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);會發現運行結果為:

    2013-07-24 17:07:17.577 NSThreadAndBlockDemo[2247:12e03] dispatch_barrier_async  
    2013-07-24 17:07:18.579 NSThreadAndBlockDemo[2247:15207] dispatch_async3  
    2013-07-24 17:07:19.578 NSThreadAndBlockDemo[2247:12b03] dispatch_async2  
    2013-07-24 17:07:20.577 NSThreadAndBlockDemo[2247:12303] dispatch_async1 
    

    說明dispatch_barrier_async的順序執行還是依賴queue的類型啊,必需要queue的類型為dispatch_queue_create創建的,而且attr參數值必需是DISPATCH_QUEUE_CONCURRENT類型,前面兩個非dispatch_barrier_async的類型的執行是依賴其本身的執行時間的,如果attr如果是DISPATCH_QUEUE_SERIAL時,那就完全是符合Serial queue的FIFO特征了。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容