GCD中的三種隊(duì)列類型
GCD編程的核心就是dispatch隊(duì)列,dispatch block的執(zhí)行最終都會(huì)放進(jìn)某個(gè)隊(duì)列中去進(jìn)行.
- The main queue (主線程串行隊(duì)列):與主線程功能相同,提交到main queue的任務(wù)會(huì)在主線程中執(zhí)行
dispatch_get_main_queue() 來獲取
- Global queue (全局并發(fā)隊(duì)列):全局并發(fā)隊(duì)列由整個(gè)進(jìn)程共享,有高,中(默認(rèn)),低,后臺四個(gè)優(yōu)先級別
dispatch_get_global_queue() 可以設(shè)置優(yōu)先級
- Custom queue(自定義隊(duì)列) 可以串行,也可以并發(fā)
dispatch_queue_create()
Group queue(隊(duì)列組): 將多線程進(jìn)行分組,最大的好處是可獲知所有線程的完成情況
可以通過dispatch_group_create()來獲取,通過dispatch_group_notify,可以直接監(jiān)聽組里所有線程的完成情況.
GCD中相關(guān)函數(shù)的使用一般都是以dispatch開頭
The Main Queue 主線程串行隊(duì)列
dispatch_sync同步執(zhí)行任務(wù)函數(shù)不會(huì)開啟新的線程
dispatch_async異步執(zhí)行任務(wù),會(huì)開啟新的線程
1.獲取主線程串行隊(duì)列
dispatch_queue_t mainQueue = dispatch_get_main_queue();
2.主線程串行隊(duì)列同步執(zhí)行任務(wù),在主線程運(yùn)行時(shí),會(huì)產(chǎn)生死鎖
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_sync (mainQueue, ^{
NSLog(@"Main Queue");
});
程序一直處在等待狀態(tài),block中的代碼將執(zhí)行不到
3.主線程串行隊(duì)列異步執(zhí)行任務(wù),在主線程中運(yùn)行,不會(huì)產(chǎn)生死鎖.
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_async(mainQueue, ^{
NSLog(@"Main Queue");
});
程序正常運(yùn)行block中的代碼正常運(yùn)行
4.從子線程異步返回主線程更新UI
dispatch_queue_t globalQueue = dispath_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(globalQueue, ^{
NSURL *url = [NSURL URLWithString:@"http://www.baidu.com"];
NSError *error; //子線程異步執(zhí)行下載操作,防止主線程卡頓
NSString *htmlDate = [NSString stringWithContentOfURL:url encoding: NSUTF8StringEncoding error:&error];
if (htmlDate != nil){
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_async(mainQueue, ^{
//異步返回主線程,根據(jù)獲取的數(shù)據(jù),更新UI
});
}else{
NSLog(@"error when download: %@", error);
}
});
主線程串行隊(duì)列由系統(tǒng)默認(rèn)生產(chǎn),無法調(diào)用dispatch_resume()和dispatch_suspend()來執(zhí)行繼續(xù)和中斷
Global Queue 全局并發(fā)隊(duì)列
耗時(shí)的操作,比如讀取網(wǎng)絡(luò)數(shù)據(jù),IO數(shù)據(jù)庫讀寫等,我們會(huì)在另一個(gè)線程中處理這些操作,然后通過主線程更新界面
1.獲取全局并發(fā)隊(duì)列
dispatch_queue_t globalQueue1 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //默認(rèn)隊(duì)列級別,一般不做修改
dispatch_queue_t globalQueue2 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_queue_t globalQueue3 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0);
dispatch_queue_t globalQueue4 = dispatch_get_global_queue(DISPATCH_QUEUE_BACKGROUND, 0);
2.全局并發(fā)隊(duì)列同步執(zhí)行任務(wù),在主線程中執(zhí)行會(huì)導(dǎo)致頁面卡頓
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NSLog(@"current task");
dispatch_sync(globalQueue, ^{
sleep(2.0);
NSLog(@"sleep 2.0s");
});
NSLog(@"next task");
控制臺輸出如下: current task -> sleep 2.0s -> next task
2s 鐘之后,才會(huì)執(zhí)行block代碼段下面的代碼
3.全局并發(fā)隊(duì)列異步執(zhí)行任務(wù),在主線程運(yùn)行,會(huì)開啟新的子線程去執(zhí)行任務(wù),頁面不會(huì)卡頓.
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NSLog(@"current task");
dispatch_async(globalQueue, ^{
sleep(2.0);
NSLog(@"sleep 2.0");
});
NSLog(@"next task");
控制臺輸出信息: current task -> next task -> sleep 2.0s
主線程不用等待2s鐘,繼續(xù)執(zhí)行block代碼段后面的代碼
4.多個(gè)全局并發(fā)隊(duì)列,異步執(zhí)行任務(wù).
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NSLog(@"current task");
dispatch_async(globalQueue, ^{
NSLog(@"最先加入全局并發(fā)隊(duì)列");
});
dispatch_async(globalQueue, ^{
NSLog(@"次加入全局并發(fā)隊(duì)列");
});
NSLog(@"next task");
控制臺輸出:
current task -> next task -> 高優(yōu)先級 -> 次優(yōu)先級
異步線程的執(zhí)行順序是不確定的,幾乎同步開始執(zhí)行
全局并發(fā)隊(duì)列由系統(tǒng)默認(rèn)生成的,所以無法調(diào)用dispatch_resum()和dispatch_suspend來控制執(zhí)行繼續(xù)和中斷
Custom Queue 自定義隊(duì)列
1. 自定義串行隊(duì)列
1.1 獲取自定義串行隊(duì)列
dispatch_queue_t serialQueue = dispatch_queue_create("com.dullgrass.serialQueue", DISPATCH_QUEUE_SERIAL); // com.dullgrass.serialQueue 是給queue起的標(biāo)識 DISPATCH_QUEUE_SERIAL 隊(duì)列類型,串行或者并發(fā)
NSLog(@"%s", dispatch_queue_get_label(conCurrentQueue));
1.2 控制臺輸出
com.dullgrass.serialQueue
1.3 自定義串行隊(duì)列同步執(zhí)行任務(wù)
dispatch_queue_t serialQueue = dispatch_queue_create("com.dullgrass.serialQueue", DISPATCH_QUEUE_SERIAL);
NSLog(@"current task");
dispatch_sync(serialQueue, ^{
NSLog(@"最先加入自定義串行隊(duì)列");
sleep(2.0);
});
dispatch_sync(serialQueue, ^{
NSLog(@"次加入自定義串行隊(duì)列");
});
NSLog(@"next task");
1.4 控制臺輸出
current task -> 最優(yōu) -> 次 -> next task
當(dāng)前線程等待串行隊(duì)列中的子線程執(zhí)行完成之后再執(zhí)行
串行隊(duì)列中先進(jìn)入子線程的隊(duì)列,執(zhí)行完成以后再執(zhí)行隊(duì)列中后面的任務(wù).
1.5 自定義串行隊(duì)列嵌套執(zhí)行同步任務(wù),產(chǎn)生死鎖
dispatch_queue_t serialQueue = dispatch_queue_create("com.dullgrass.serialQueue", DISPATCH_QUEUE_SERIAL);
dispatch_sync(serialQueue, ^{
//該代碼段后面的代碼不會(huì)執(zhí)行,程序被鎖死
NSLog(@"會(huì)執(zhí)行的代碼");
dispatch_sync(serialQueue, ^{
NSLog(@"代碼不執(zhí)行");
});
});
1.6 異步執(zhí)行串行隊(duì)列嵌套同步執(zhí)行串行隊(duì)列中的任務(wù),將不會(huì)被執(zhí)行,其他程序正常執(zhí)行
dispatch_queue_t serialQueue = dispatch_queue_create("com.dullgrass.serialQueue", DISPATCH_QUEUE_SERIAL);
dispatch_async(serialQueue, ^{
NSLog(@"會(huì)執(zhí)行的代碼");
dispatch_sync(serialQueue, ^{
NSLog(@"代碼不會(huì)執(zhí)行");
})
});
注意??: 不要嵌套使用同步執(zhí)行的串行隊(duì)列任務(wù)
2. 自定義并發(fā)隊(duì)列
2.1 獲取自定義并發(fā)隊(duì)列
dispatch_queue_t conCurrentQueue = dispatch_queue_create("com.dullgrass.conCurrentQueue", DISPATCH_QUEUE_CONCURRENT);
2.2 自定義并發(fā)隊(duì)列執(zhí)行同步任務(wù)
dispatch_queue_t conCurrentQueue = dispatch_queue_create("com.dullgrass.conCurrentQueue", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"current task");
dispatch_sync(conCurrentQueue, ^{
NSLog(@"先加入隊(duì)列");
});
dispatch_sync(conCurrentQueue, ^{
NSLog(@"次加入隊(duì)列");
});
NSLog(@"next task");
2.3 控制臺輸出如下
current task -> 先 -> 次 -> next task
2.4 自定義并發(fā)隊(duì)列嵌套執(zhí)行同步任務(wù)(不會(huì)產(chǎn)生死鎖,程序正常運(yùn)行)
dispatch_queue_t conCurrentQueue = dispatch_queue_create("com.dullgrass.conCurrentQueue", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"current task");
dispatch_sync(conCurrentQueue, ^{
NSLog(@"先加入隊(duì)列");
dispatch_sync(conCurrentQueue, ^{
NSLog(@"次加入隊(duì)列");
});
});
NSLog(@"next task");
輸出:
current task -> 先加入隊(duì)列 -> 次加入隊(duì)列 -> next task
2.5 自定義并發(fā)隊(duì)列執(zhí)行異步任務(wù)
dispatch_queue_t conCurrentQueue = dispatch_queue_create("com.dullgrass.conCurrentQueue", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"current task");
dispatch_async(conCurrentQueue, ^{
NSLog(@"先加入隊(duì)列");
});
dispatch_async(conCurrentQueue, ^{
NSLog(@"次加入隊(duì)列");
});
NSLog(@"next task");
輸出:
current task -> next task -> 次 -> 先
異步執(zhí)行任務(wù),開啟新的子線程,不影響當(dāng)前線程任務(wù)的執(zhí)行,并行隊(duì)列中的任務(wù),幾乎是同步執(zhí)行的,輸出順序不確定