1.什么是GCD
GCD 全程為 Grand Central Dispatch 是異步執(zhí)行任務(wù)的技術(shù)之一
2.Dispatch Queue
2.1 Serial Dispatch Queue
FIFO 先進(jìn)先出原則,等待現(xiàn)在執(zhí)行中的任務(wù)處理結(jié)束,是串行線程
2.2ConcurrentQueue
并行線程
2.3 Dispatch Queue的種類
Main Dispatch Queue(主線程執(zhí)行 串行隊(duì)列)
Global Dispatch Queue (High Priority 并行隊(duì)列 優(yōu)先級(jí)最高)
Global Dispatch Queue (Default Priority 并行隊(duì)列 優(yōu)先級(jí)默認(rèn))
Global Dispatch Queue (Low Priority 并行隊(duì)列 優(yōu)先級(jí)低)
Global Dispatch Queue (Background Priority 并行隊(duì)列 優(yōu)先級(jí)后臺(tái))
2.4 dispatch_set_target_queue
當(dāng)用dispatch_queue_create生成的dispatch queue需要改變執(zhí)行優(yōu)先級(jí)用到的函數(shù)
2.5 dispatch_after
延遲執(zhí)行處理,需要注意的是,dispatch_after 并不是在指定時(shí)間后執(zhí)行處理,而只是在指定時(shí)間追加處理到dispatch queue
2.6 dispatch_group
在單個(gè)線程中想要等線程結(jié)束之后執(zhí)行結(jié)束處理,這時(shí)候我們需要用到dispatch group 代碼如下
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, globalQueue, ^{
NSLog(@"block 1");
});
dispatch_group_async(group, globalQueue, ^{
NSLog(@"block 2");
});
dispatch_group_async(group, globalQueue, ^{
NSLog(@"block 3");
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"block finish");
});
輸出打印 block 1 2 3執(zhí)行順序不定,但是finish一定是最后輸出的
2.7 dispatch_barrier_async
在訪問(wèn)數(shù)據(jù)時(shí),用serial queue 我們可以避免數(shù)據(jù)競(jìng)爭(zhēng)的問(wèn)題,但是如果為了高效的對(duì)數(shù)據(jù)庫(kù)進(jìn)行讀寫,我們需要引入concurrent dispatch queue,但是我們知道concurrent dispatch queue是并行線程,如果我們需要在讀取的線程內(nèi)添加寫的線程,這時(shí)候就會(huì)引發(fā)讀取與寫入的不符合,或者因?yàn)榉欠ㄔL問(wèn)導(dǎo)致異常結(jié)束,因此我們需要dispatch_barrier_async 看如下代碼
__block int readValue1 = 1;
__block int readValue2 = 1;
dispatch_queue_t conCurrentQueue = dispatch_queue_create("con_current_queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(conCurrentQueue, ^{
NSLog(@"block1 readValue1=%d,readValue2=%d",readValue1,readValue2);
});
dispatch_async(conCurrentQueue, ^{
NSLog(@"block2 readValue1=%d,readValue2=%d",readValue1,readValue2);
});
dispatch_async(conCurrentQueue, ^{
NSLog(@"block3 readValue1=%d,readValue2=%d",readValue1,readValue2);
});
dispatch_async(conCurrentQueue, ^{
readValue1 = 2;
});
dispatch_async(conCurrentQueue, ^{
NSLog(@"block4 readValue1=%d,readValue2=%d",readValue1,readValue2);
});
dispatch_async(conCurrentQueue, ^{
NSLog(@"block5 readValue1=%d,readValue2=%d",readValue1,readValue2);
});
dispatch_barrier_async(conCurrentQueue, ^{
readValue2 = 2;
});
dispatch_async(conCurrentQueue, ^{
NSLog(@"block6 readValue1=%d,readValue2=%d",readValue1,readValue2);
});
dispatch_async(conCurrentQueue, ^{
NSLog(@"block7 readValue1=%d,readValue2=%d",readValue1,readValue2);
});
/*
block1 readValue1=1,readValue2=1
block2 readValue1=1,readValue2=1
block4 readValue1=2,readValue2=1
block3 readValue1=2,readValue2=1
block5 readValue1=2,readValue2=1
block6 readValue1=2,readValue2=2
block7 readValue1=2,readValue2=2
*/
看打印 我們知道dispatch_barrier_async 是等前面的線程執(zhí)行完才去執(zhí)行,相當(dāng)于阻斷并行線程的作用
2.7 dispatch_apply
dispatch_apply 是dispatch_sync和dispatch_group的關(guān)聯(lián)API
2.8 dispatch_suspend /dispatch_resume
掛起某個(gè)線程和恢復(fù)某個(gè)線程
2.9 dispatch_semaphore
我們先看一段代碼
NSMutableArray *array = [[NSMutableArray alloc]init];
for(int i=0;i<10000;i++){
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[array addObject:[NSNumber numberWithInt:i]];
});
}
該代碼由內(nèi)存錯(cuò)誤導(dǎo)致程序異常
dispatch_semaphore 使用計(jì)數(shù)來(lái)實(shí)現(xiàn)功能,當(dāng)計(jì)數(shù)為0時(shí)等待,當(dāng)計(jì)數(shù)為1或者大于1時(shí),減去1而不等待
NSMutableArray *array = [[NSMutableArray alloc]init];
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
for(int i=0;i<10000;i++){
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//等待semaphore -1操作,相當(dāng)于線程阻塞
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
[array addObject:[NSNumber numberWithInt:i]];
//semaphore +1操作
dispatch_semaphore_signal(semaphore);
});
}