《Objective-C 高級編程》學習筆記3-GCD


獅子頭鎮樓編程

《Objective-C 高級編程》學習筆記1-內存管理

《Objective-C 高級編程》學習筆記2-Blocksbash


1   什麼是 GCD

將應用程序中記述的線程管理用的代碼在系統級中實現。開發者只須要定義想要執行的任務並追加到適當的 Dispatch Queue 中,GCD就能生成必要的線程並計劃執行任務。async


2   GCD 的 API

dispatch_async(queue, ^{
    /* * 想執行的任務 */
})複製代碼

該源碼使用 Block 語法「定義想執行的任務」,經過 dispatch_async 函數「追加」賦值在變量 queue 的「Dispatch Queue中」。函數

2.一、Dispatch Queue

Dispatch Queue:執行處理的等待隊列。有兩種:oop

  • Serial Dispatch Queue,串行隊列
  • Concurrent Dispatch Queue,並行隊列

2.二、dispatch_queue_create

//建立串行隊列
dispatch_queue_t mySerialDispatchQueue = dispatch_queue_create("com.gcd.mySerialDispatchQueue", NULL);
dispatch_async(mySerialDispatchQueue, ^{
    //在串行隊列中執行Block
});
    
//建立並行隊列
dispatch_queue_t myConcurrentDispatchQueue = dispatch_queue_create("com.gcd.myConcurrentDispatchQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(myConcurrentDispatchQueue, ^{
    //在並行隊列中執行Block
});
複製代碼

2.三、Main Dispatch Queue / Global Dispatch Queue

這是系統標準提供的 Dispatch Queue

2.3.一、Main Dispatch Queue
post

主線程執行的的 Dispatch Queue,由於主線程只有一個,因此它必定是串行隊列

追加到 Main Dispatch Queue 的處理在主線程的 RunLoop 中執行。所以用戶界面的操做等一些必須在主線程中執行的處理追加到 Main Dispatch Queue 中使用。學習

2.3.二、Global Dispatch Queueui

是全部應用程序都可以使用的並行隊列,它有四個優先級。


///主隊列獲取
dispatch_queue_t mdq = dispatch_get_main_queue();
    
//全局隊列,執行優先級:高
dispatch_queue_t gdq_high = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
//全局隊列,執行優先級:中
dispatch_queue_t gdq_default = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//全局隊列,執行優先級:低
dispatch_queue_t gdq_low = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
//全局隊列,執行優先級:後臺
dispatch_queue_t gdq_background = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);

複製代碼

2.四、dispatch_set_target_queue

dispatch_queue_create 函數生成的 Dispatch Queue 無論是 串行隊列 仍是 並行隊列,都使用與默認優先級 Global Dispatch Queue 相同執行優先級的線程。可以使用 dispatch_set_target_queue 函數變動 Dispatch Queue 的執行優先級。spa

2.五、dispatch_after

可以使用 dispatch_after 執行指定時間後執行的處理。注意:dispatch_after 函數並非在指定時間後執行處理,而只是在指定時間追加處理到 Dispatch Queue 。線程

dispatch_time_t dt = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
dispatch_after(dt, dispatch_get_main_queue(), ^{
    //執行操做的block
});複製代碼

2.六、Dispatch Group

在追加到 Dispatch Queue 中的多個處理所有結束後想執行結束處理的時候使用。

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, ^{ NSLog(@"blk0"); });
dispatch_group_async(group, queue, ^{ NSLog(@"blk1"); });
dispatch_group_async(group, queue, ^{ NSLog(@"blk2"); });
dispatch_group_async(group, queue, ^{ NSLog(@"blk3"); });
    
dispatch_group_notify(group, dispatch_get_main_queue(), ^{ NSLog(@"done"); });
複製代碼

2.七、dispatch_sync

  • async 意味着 「非同步」,dispatch_async 函數不作任何等待。
  • sync 意味着 「同步」,dispatch_sync 函數會將指定的 Block 「同步」 追加到指定的 Dispatch Queue 中。在追加 Block 結束以前,dispatch_sync 函數會一直等待。

dispatch_sync 使用不當會形成一個很嚴重的問題:死鎖。

dispatch_sync(dispatch_get_main_queue(), ^{
    NSLog(@"同步任務在 %@ 執行", [NSThread currentThread]);
});

//一、主線程正在執行主隊列的任務;
//二、一個同步任務過來了,因而,主線程當即等待;
//三、同步任務在等主線程當前任務完成,然而主線程在等待這個同步任務執行;
//四、因而就形成了相互等待的狀況。
複製代碼

2.八、dispatch_once

dispatch_once 函數是保證在應用程序執行中只執行以此指定處理的API。如初始化單例。

+ (instancetype)share {
    static id instance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[self alloc] init];
    });
    return instance;
}複製代碼


3   GCD 實現

3.一、Dispatch Queue

GCD 的 Dispatch Queue 很是方便,實現 GCD 須要:

  • 用於管理追加的 Block 的 C語言層實現的 FIFO 隊列。
  • Atomic 函數中實現的用於排他控制的輕量級信號。
  • 用於管理線程的C語言層實現的一些容器。
相關文章
相關標籤/搜索