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; }