學(xué)習(xí)完本篇漩蟆,您會對以下知識點(diǎn)更加理解:
- 隊(duì)列
- 串行隊(duì)列
- 并發(fā)隊(duì)列
- GCD全局隊(duì)列
- GCD主隊(duì)列
- 創(chuàng)建串行隊(duì)列
- 創(chuàng)建并發(fā)隊(duì)列
隊(duì)列
不管是什么隊(duì)列烙肺,一定是FIFO隊(duì)列饮焦,即先進(jìn)先出眼虱。
所以马胧,請大家記住了:不管是串行隊(duì)列(SerialQueue)還是并發(fā)隊(duì)列(ConcurrencyQueue)宴卖,都是FIFO隊(duì)列滋将。也就意味著,任務(wù)一定是一個一個地症昏,按照先進(jìn)先出的順序來執(zhí)行随闽。
串行隊(duì)列:在創(chuàng)建隊(duì)列時,傳參數(shù)DISPATCH_QUEUE_SERIAL表示創(chuàng)建串行隊(duì)列肝谭。任務(wù)會一個一個地執(zhí)行掘宪,只有前一個任務(wù)執(zhí)行完成,才會繼續(xù)執(zhí)行下一個任務(wù)分苇。串行執(zhí)行并不是同步執(zhí)行的意思添诉,一定要注意區(qū)分
并發(fā)隊(duì)列:在創(chuàng)建隊(duì)列時,傳參數(shù)DISPATCH_QUEUE_CONCURRENT表示創(chuàng)建并發(fā)隊(duì)列医寿。并發(fā)隊(duì)列會盡可能多地創(chuàng)建線程去執(zhí)行任務(wù)栏赴。并發(fā)隊(duì)列中的任務(wù)會按入隊(duì)的順序執(zhí)行任務(wù),但是哪個任務(wù)先完成是不確定的靖秩。
隊(duì)列類型
蘋果提供了以下隊(duì)列:
全局隊(duì)列:蘋果預(yù)定義的全局并發(fā)隊(duì)列须眷,只能通過蘋果提供的API來獲取,可以設(shè)置優(yōu)先級沟突。
主隊(duì)列:在應(yīng)用啟動的時候花颗,就會自動創(chuàng)建與主線程關(guān)聯(lián)的串行隊(duì)列,我們也可能獲取惠拭,不能手動創(chuàng)建扩劝。
手動創(chuàng)建串行隊(duì)列
手動創(chuàng)建并發(fā)隊(duì)列
全局隊(duì)列
全局隊(duì)列的第二個參數(shù)用于設(shè)置優(yōu)先級庸论,只有下面四個選項(xiàng):
DISPATCH_QUEUE_PRIORITY_HIGH 2
DISPATCH_QUEUE_PRIORITY_DEFAULT 0
DISPATCH_QUEUE_PRIORITY_LOW (-2)
DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN"
我們通常使用默認(rèn)選項(xiàng),所以很多時候看到的都是傳0棒呛。下面我們來看看創(chuàng)建四個任務(wù)放到并發(fā)隊(duì)列中異步地執(zhí)行:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"1");
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 睡眠2秒
sleep(2);
NSLog(@"2");
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 睡眠3秒
sleep(1);
NSLog(@"3");
});
打印結(jié)果如下:
三個任務(wù)分別在三個線程中進(jìn)行才有三個線程號聂示。
上面的代碼中,我們在并發(fā)隊(duì)列中添加了三個任務(wù)簇秒,其中任務(wù)1是直接執(zhí)行鱼喉,任務(wù)2是在異步執(zhí)行過程中被睡眠2秒,任務(wù)3在異步執(zhí)行過程中被睡眠1秒趋观,結(jié)果任務(wù)3先于任務(wù)2執(zhí)行完成扛禽。說明并發(fā)執(zhí)行任務(wù)并不需要等待其他任務(wù)先執(zhí)行完。對于這三個任務(wù)皱坛,是互不干擾的编曼!
當(dāng)然,全局隊(duì)列可以指定任務(wù)執(zhí)行的優(yōu)先級的麸恍,比如下面:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
NSLog(@"4");
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
NSLog(@"3");
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"2");
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSLog(@"1");
});
優(yōu)先級由高到低順序運(yùn)行 任務(wù)一優(yōu)先級最高灵巧,所以在并發(fā)隊(duì)列中優(yōu)先執(zhí)行。
主隊(duì)列
主隊(duì)列是應(yīng)用程序啟動時抹沪,由系統(tǒng)預(yù)先創(chuàng)建的刻肄,與主線程相關(guān)聯(lián)的隊(duì)列。我們只能通過系統(tǒng)API來獲取主隊(duì)列融欧,不能手動創(chuàng)建它索守。下面我們來看看主隊(duì)列這個串行隊(duì)列的執(zhí)行順序如何:
dispatch_async(dispatch_get_main_queue(), ^{
sleep(2);
NSLog(@"main 1");
});
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"main 2");
});
dispatch_async(dispatch_get_main_queue(), ^{
sleep(1);
NSLog(@"main 3");
});
運(yùn)行結(jié)果如下:
從打印結(jié)果可看到執(zhí)行的順序是按入隊(duì)的順序來執(zhí)行的为严。雖然讓任務(wù)1睡眠2秒再執(zhí)行,其他任務(wù)也只能等待任務(wù)1完成,才能繼承執(zhí)行任務(wù)2窒篱,在任務(wù)2執(zhí)行完成灿里,才能執(zhí)行任務(wù)3忱详。
從打印結(jié)果可以看到線程號是固定的骑晶,說明都在同一個線程中執(zhí)行,而這個線程就是主線程刺桃。任務(wù)只能一個一個地執(zhí)行粹淋。
創(chuàng)建串行隊(duì)列
通過dispatch_queue_create函數(shù)來創(chuàng)建隊(duì)列,參數(shù)一是一個C語言的字符串瑟慈,是隊(duì)列的標(biāo)簽桃移,也就是名稱,參數(shù)二是指定串行隊(duì)列還是并發(fā)隊(duì)列葛碧。
創(chuàng)建串行隊(duì)列傳:DISPATCH_QUEUE_SERIAL(也就是NULL)
創(chuàng)建并發(fā)隊(duì)列傳:DISPATCH_QUEUE_CONCURRENT
dispatch_queue_t serialQueue = dispatch_queue_create("serial_queue",
DISPATCH_QUEUE_SERIAL);
dispatch_async(serialQueue, ^{
NSLog(@"s1");
});
dispatch_async(serialQueue, ^{
sleep(2);
NSLog(@"s2");
});
dispatch_async(serialQueue, ^{
sleep(1);
NSLog(@"s3");
});
打印結(jié)果如下:
創(chuàng)建的串行隊(duì)列只在一個線程運(yùn)行借杰。
創(chuàng)建并發(fā)隊(duì)列
通過dispatch_queue_create函數(shù)來創(chuàng)建隊(duì)列,參數(shù)一是一個C語言的字符串进泼,是隊(duì)列的標(biāo)簽蔗衡,也就是名稱纤虽,參數(shù)二是指定串行隊(duì)列還是并發(fā)隊(duì)列。
創(chuàng)建串行隊(duì)列傳:DISPATCH_QUEUE_SERIAL(也就是NULL)
創(chuàng)建并發(fā)隊(duì)列傳:DISPATCH_QUEUE_CONCURRENT
一起來看看串行隊(duì)列是否需要等待任務(wù)執(zhí)行完成粘都,下一個任務(wù)才能開始:
dispatch_queue_t concurrencyQueue = dispatch_queue_create("com.huangyibiao.concurrency-queue",
DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrencyQueue, ^{
NSLog(@"s1");
});
dispatch_async(concurrencyQueue, ^{
sleep(2);
NSLog(@"s2");
});
dispatch_async(concurrencyQueue, ^{
sleep(1);
NSLog(@"s3");
});
打印結(jié)果:
從打印結(jié)果可以看出來廓推,任務(wù)在三個子線程中執(zhí)行刷袍,且互不干擾翩隧,不需要等待其他任務(wù)完成,就可以并發(fā)地分別去執(zhí)行呻纹!