首先,我們先來看一下GCD 的簡單介紹.
GCD是 Apple 開發(fā)的一個(gè)多核編程的解決方法斩祭,簡單易用,效率高粘衬,速度快。通過 GCD咳促,開發(fā)者只需要向隊(duì)列中添加一段代碼塊(block或C函數(shù)指針)稚新,而不需要直接和線程打交道。GCD在后端管理著一個(gè)線程池跪腹,它不僅決定著你的代碼塊將在哪個(gè)線程被執(zhí)行褂删,還根據(jù)可用的系統(tǒng)資源對(duì)這些線程進(jìn)行管理。這樣通過GCD來管理線程尺迂,從而解決線程被創(chuàng)建的問題笤妙。
學(xué)習(xí)GCD 之前适刀,先來了解 GCD 中兩個(gè)核心概念:任務(wù)和隊(duì)列世蔗。
任務(wù):就是執(zhí)行操作的意思,換句話說就是你在線程中執(zhí)行的那段代碼暑认。在 GCD 中是放在 block 中的膳音。
執(zhí)行任務(wù)有兩種方式:同步執(zhí)行(sync)和異步執(zhí)行(async)召衔。兩者的主要區(qū)別是:是否等待隊(duì)列的任務(wù)執(zhí)行結(jié)束,以及是否具備開啟新線程的能力祭陷。
同步執(zhí)行(sync):
同步添加任務(wù)到指定的隊(duì)列中苍凛,在添加的任務(wù)執(zhí)行結(jié)束之前趣席,會(huì)一直等待,直到隊(duì)列里面的任務(wù)完成之后再繼續(xù)執(zhí)行醇蝴。
只能在當(dāng)前線程中執(zhí)行任務(wù)宣肚,不具備開啟新線程的能力。
異步執(zhí)行(async):
異步添加任務(wù)到指定的隊(duì)列中悠栓,它不會(huì)做任何等待霉涨,可以繼續(xù)執(zhí)行任務(wù)。
可以在新的線程中執(zhí)行任務(wù)惭适,具備開啟新線程的能力笙瑟。
隊(duì)列(Dispatch Queue):這里的隊(duì)列指執(zhí)行任務(wù)的等待隊(duì)列,即用來存放任務(wù)的隊(duì)列癞志。隊(duì)列是一種特殊的線性表往枷,采用 FIFO(先進(jìn)先出)的原則,即新任務(wù)總是被插入到隊(duì)列的末尾凄杯,而讀取任務(wù)的時(shí)候總是從隊(duì)列的頭部開始讀取错洁。每讀取一個(gè)任務(wù),則從隊(duì)列中釋放一個(gè)任務(wù)盾舌。
在 GCD 中有兩種隊(duì)列:串行隊(duì)列和并發(fā)隊(duì)列墓臭。兩者都符合 FIFO(先進(jìn)先出)的原則蘸鲸。兩者的主要區(qū)別是:執(zhí)行順序不同妖谴,以及開啟線程數(shù)不同。
串行隊(duì)列(Serial Dispatch Queue):
每次只有一個(gè)任務(wù)被執(zhí)行酌摇。讓任務(wù)一個(gè)接著一個(gè)地執(zhí)行膝舅。(只開啟一個(gè)線程,一個(gè)任務(wù)執(zhí)行完畢后窑多,再執(zhí)行下一個(gè)任務(wù))
并發(fā)隊(duì)列(Concurrent Dispatch Queue):
可以讓多個(gè)任務(wù)并發(fā)(同時(shí))執(zhí)行仍稀。(可以開啟多個(gè)線程,并且同時(shí)執(zhí)行任務(wù))
下面有代碼具體演示執(zhí)行方式與隊(duì)列結(jié)合使用的時(shí)候,各種情況的區(qū)別.
1.串行隊(duì)列 同步執(zhí)行
NSLog(@"開始了");
dispatch_queue_t serQueue = dispatch_queue_create("feng", DISPATCH_QUEUE_SERIAL);
dispatch_sync(serQueue, ^{
for (int i = 0; i<10; i++) {
NSLog(@"1111-%d --- %@", i, [NSThread currentThread]);
}
});
dispatch_sync(serQueue, ^{
for (int i = 0; i<10; i++) {
NSLog(@"2222-%d --- %@", i, [NSThread currentThread]);
}
});
NSLog(@"結(jié)束了");
如上圖所示,任務(wù)一加入就開始執(zhí)行, 并且按照順序執(zhí)行, 不開辟線程.
2.串行隊(duì)列 異步執(zhí)行
NSLog(@"開始了");
dispatch_queue_t serQueue = dispatch_queue_create("feng", DISPATCH_QUEUE_SERIAL);
dispatch_async(serQueue, ^{
for (int i = 0; i<10; i++) {
NSLog(@"1111-%d --- %@", i, [NSThread currentThread]);
}
});
dispatch_async(serQueue, ^{
for (int i = 0; i<10; i++) {
NSLog(@"2222-%d --- %@", i, [NSThread currentThread]);
}
});
NSLog(@"結(jié)束了");
如上圖所示,任務(wù)全部加入才開始執(zhí)行, 按照順序執(zhí)行, 開辟線程.
3.并行隊(duì)列 同步執(zhí)行
NSLog(@"開始了");
dispatch_queue_t serQueue = dispatch_queue_create("feng", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(serQueue, ^{
for (int i = 0; i<10; i++) {
NSLog(@"1111-%d --- %@", i, [NSThread currentThread]);
}
});
dispatch_sync(serQueue, ^{
for (int i = 0; i<10; i++) {
NSLog(@"2222-%d --- %@", i, [NSThread currentThread]);
}
});
NSLog(@"結(jié)束了");
如上圖所示,任務(wù)一加入就開始執(zhí)行, 按照順序執(zhí)行, 不開辟線程.
4.并行隊(duì)列 異步執(zhí)行
NSLog(@"開始了");
dispatch_queue_t serQueue = dispatch_queue_create("feng", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(serQueue, ^{
for (int i = 0; i<10; i++) {
NSLog(@"1111-%d --- %@", i, [NSThread currentThread]);
}
for (int i = 0; i<10; i++) {
NSLog(@"2222-%d --- %@", i, [NSThread currentThread]);
}
});
dispatch_async(serQueue, ^{
for (int i = 0; i<10; i++) {
NSLog(@"3333-%d --- %@", i, [NSThread currentThread]);
}
for (int i = 0; i<10; i++) {
NSLog(@"4444-%d --- %@", i, [NSThread currentThread]);
}
});
NSLog(@"結(jié)束了");
如上圖所示,任務(wù)全部加入才開始執(zhí)行, 并發(fā)執(zhí)行, 開辟線程.
總結(jié):
1.同步(dispatch_sync) 任務(wù)一進(jìn)入任務(wù)就直接開始執(zhí)行. 不開辟線程.
2.異步(dispatch_async) 所有的任務(wù)都進(jìn)入了,才開始執(zhí)行,會(huì)開辟線程.
追加的其他功能:
柵欄函數(shù)dispatch_barrier_async的使用
// 1.創(chuàng)建并發(fā)隊(duì)列
dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
// 2.向隊(duì)列中添加任務(wù)
dispatch_async(queue, ^{ // 1.2是并行的
NSLog(@"任務(wù)1, %@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"任務(wù)2, %@",[NSThread currentThread]);
});
dispatch_barrier_async(queue, ^{
NSLog(@"任務(wù) barrier, %@", [NSThread currentThread]);
});
dispatch_async(queue, ^{ // 這兩個(gè)是同時(shí)執(zhí)行的
NSLog(@"任務(wù)3, %@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"任務(wù)4, %@",[NSThread currentThread]);
});
如上圖所示,注意: 輸出結(jié)果: 任務(wù)1 任務(wù)2 ——》 任務(wù) barrier ——》任務(wù)3 任務(wù)4
// 其中的任務(wù)1與任務(wù)2埂息,任務(wù)3與任務(wù)4 由于是并行處理先后順序不定技潘。