iOS GCD經常使用函數總結

GCD提供兩種Dispatch Queue, 分別爲Concurrent Dispatch Queue 和 Serial Dispatch Queue. 數據庫

Serial Dispatch Queue 使用一個thread。 安全

Concurrent Dispatch Queue 使用多個thread。 多線程

獲取Dispatch Queue: 併發

0)dispatch_queue_create app

dispatch_queue_t queue = dispatch_queue_create("name.of.your.queue",NULL);
第一個參數爲queue的名字,第二個參數傳NULL代表要建立一個Serial Dispatch Queue, 傳入DISPATCH_QUEUE_CONCURRENT 建立一個 Concurrent Dispatch Queue。

若是是對數據庫表更新或更新文件,最好爲每個表或文件創建一個Serial Dispatch Queue,這樣能保證只有一個thread會對數據進行更新。 async

若是對那些不會引發數據不一致問題的任務,須要放到Concurrent Dispatch Queue執行。 函數

1)從Main Dispatch Queue/Global Dispatch Queue獲取 spa

//main queue
dispatch_queue_t mainQueue = dispatch_get_main_queue();

//global queue of high priority
dispatch_queue_t globalHigh = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0);

//global queue of default priority
dispatch_queue_t globalDefault = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

//global queue of low priority
dispatch_queue_t globalLow = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0);

//global queue of background priority
dispatch_queue_t globalBackground = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0);
Main Dispatch Queue -> Serial dispatch queue

Global Dispatch Queue -> Concurrent dispatch queue 線程

dispatch_set_target_queue: 主要用來給新建的queue設置優先級 code

dispatch_queue_t serialQueue = dispatch_queue_create("name.of.queue",NULL);

dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0);

dispatch_set_target_queue(serialQueue, globalQueue);
須要注意的是,第一個參數是自定義的queue,而不是系統的queue。由於你不能給系統的queue設置權限。經過上面設置,serialQueue 就有了與globalQueue同樣的優先級。其實這個函數不只能夠設置queue的優先級,還能夠設置queue之間的層級結構。


dispatch_after: 過一段時間執行queue中的task

dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3ull * NSEC_PER_SEC);

dispatch_after(time, dispatch_get_main_queue(),^{
               NSLog(@"after 3 seconds...");});

Dispatch Group

0)dispatch_group_notify

dispatch group 能夠在group中的dispatch queue都執行完以後,經過一個dispatch_group_notify通知回調。

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(@"task1");});
dispatch_group_async(group, queue, ^{NSLog(@"task2");});
dispatch_group_async(group, queue, ^{NSLog(@"task3");});

dispatch_group_notify(group, dispatch_get_main_queue(), ^{NSLog(@"finished...");});

輸出總會保證"finished..."會在最後一句輸出。

1)dispatch_group_wait

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(@"task1");});
dispatch_group_async(group, queue, ^{NSLog(@"task2");});
dispatch_group_async(group, queue, ^{NSLog(@"task3");});

dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

dispatch_group_wait提供了一種相似超時的機制,固然若是等待時間設置爲DISPATCH_TIME_FOREVER,功能和dispatch_group_notify是同樣的。

dispatch_barrier_async

dispatch_barrier_async是一個可讓當前任務等待queue其餘任務完成再執行的函數。例如,從數據庫讀取數據是能夠多線程併發讀取的,由於這樣提升效率。可是,更新數據庫數據,就要保證只有一個線程進行更新操做。因此,當更新操做發生的時候,必定要保證讀操做和其餘更新操做等待。

dispatch_queue_t queue = dispatch_queue_create("barrier.queue", DISPATCH_QUEUE_CONCURRENT);

dispatch_async(queue, read_block_0);
dispatch_async(queue, read_block_1);
dispatch_async(queue, read_block_2);
dispatch_async(queue, read_block_3);
dispatch_async(queue, read_block_4);

dispatch_barrier_async(queue, update_block);

dispatch_async(queue, read_block_5);
dispatch_async(queue, read_block_6);
dispatch_async(queue, read_block_7);
dispatch_async(queue, read_block_8);
dispatch_async(queue, read_block_9);
這樣就能夠保證只有當更新操做結束後,纔會進行其餘數據庫讀操做,保證了數據的一致性。


dispatch_apply

dispatch_apply用於給一個block添加到dispatch queue若干次。 「for」循環

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

dispatch_apply(10, queue, ^(size_t index) { NSLog(@"%zu",index);});

NSLog(@"done...");

dispatch_suspend/dispatch_resume

用於暫停和繼續執行queue

dispatch semaphore

dispatch semaphore 適合處理比dispatch queue或者dispatch_barrier_async更小顆粒度的操做。

例如,

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

NSMutableArray *array = [[NSMutableArray alloc] init];

for (int i = 0; i < 100000; i++)
{
    dispatch_async(queue, ^{
      [array addObject:[NSNumber numberWithInt:i]];
    });
}

若是執行上段代碼,由於NSMutableArray不是thread safe的,因此在global queue中對其進行添加對象,會致使程序crash掉。

使用dispatch semaphore咱們能夠實現多線程對NSMutableArray進行操做

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);

NSMutableArray *array = [[NSMutableArray alloc] init];

for (int i = 0; i < 100000; i++)
{
    dispatch_async(queue, ^{

      dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

      [array addObject:[NSNumber numberWithInt:i]];

      dispatch_semaphore_signal(semaphore);
    });
}

dispatch semaphore 是一個信號量的counter,當counter爲0,當前線程中止運行,當大於0,自減1,繼續執行。

dispatch_semaphore_create

dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
初始化一個counter爲1的semaphore.

dispatch_semaphore_wait

dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
等待counter大於0才運行,第二個參數爲等待時間。執行後counter減1.

dispatch_semaphore_signal

dispatch_semaphore_signal(semaphore);
給counter加1

因此在上面的代碼中,就能夠保證在wait和signal中的[array addObject:[NSNumber numberWithInt:i]]; 就只有一個thread進行操做,保證了線程安全。

dispatch_onece

保證了dispatch_once中的代碼只會被執行一次,經常使用於單例。

+ (id)sharedManager {
    static MyManager *sharedMyManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedMyManager = [[self alloc] init];
    });
    return sharedMyManager;
}
相關文章
相關標籤/搜索