GCD 其實已經(jīng)了解了很久了尸诽,在實際工程中也會經(jīng)常用,但是其實很多實踐都是淺嘗輒止绑改。
最近又在回頭看這塊兒的內(nèi)容谢床,有一些知識點,原來不甚明白的厘线,現(xiàn)在有了新的認(rèn)識识腿,剛好也記錄下。
GCD 是一套方案造壮,GCD 本身管理了一組線程池渡讼,GCD 負(fù)責(zé)線程池中的線程創(chuàng)建銷毀骂束、并且這種能力是動態(tài)化的,即可以充分利用當(dāng)前 CPU 的多核特性成箫。
添加到 GCD 隊列中的任務(wù)展箱,會由 GCD 來決定運行在哪一個線程上。也就是說蹬昌,GCD Queue 是一個抽象概念混驰, task 是添加到 Queue 中不假,但是實際仍然是運行在線程上的皂贩。
GCD Concurrent Queue 并行隊列
GCD 的隊列中的 task 遵循 FIFO (First In First Out)原則栖榨,但是 task 完成的順序是不可測的。
上面的這段描述明刷,是在當(dāng)時閱讀官方文檔的時候婴栽,產(chǎn)生了疑惑,我的想法是辈末,既然 task 是按照先后添加到 Queue 中的順序進(jìn)行執(zhí)行的愚争,那為啥完成時間就不一定了呢?
現(xiàn)在明白了挤聘,task 的執(zhí)行壓根和 Queue 關(guān)系不大轰枝,GCD 只是按照添加順序從 Queue 中一個個拿出 task,扔到線程上去執(zhí)行檬洞。有的 task 一會就完成了狸膏,有的需要比較長的時間,當(dāng)然這個完成順序就不一定了添怔。
現(xiàn)在想想湾戳,當(dāng)時應(yīng)該是想當(dāng)然的認(rèn)為 GCD 只有在完成上一個任務(wù)后才會開啟下一個任務(wù),跟串行隊列混淆了广料,從而導(dǎo)致疑惑的砾脑。
GCD 串行隊列
串行隊列就是只有完成上一個 task ,才會進(jìn)行下一個 task 的執(zhí)行艾杏。
所以完成順序與添加順序是相同的韧衣。
Objc GCD 隊列疑惑
上圖是摘錄自 Objc.cn 中關(guān)于 GCD 隊列的一張圖。
但是在閱讀時购桑,我有下面幾點疑惑:
- 為什么 Custom Queues 這一層的關(guān)系如此復(fù)雜畅铭。
- 為什么 Serial Queue 既指向了 Serial Queue ,又能指向 Concurrent Queue勃蜘。
- 最上面一層中的 Serial Queue 和 倒數(shù)第二層中的 Queues 有什么關(guān)系硕噩。
GCD 公開有 5 個不同的隊列:運行在主線程中的 main queue,3 個不同優(yōu)先級的后臺隊列缭贡,以及一個優(yōu)先級更低的后臺隊列(用于 I/O)炉擅。 另外辉懒,開發(fā)者可以創(chuàng)建自定義隊列:串行或者并行隊列。自定義隊列非常強大谍失,在自定義隊列中被調(diào)度的所有 block 最終都將被放入到系統(tǒng)的全局隊列中和線程池中眶俩。
Objc 原文如上描述。
細(xì)細(xì)品味快鱼,其意思是颠印,GCD Queues 有 5 大欽定的 Queue。
開發(fā)者當(dāng)然也可以自定義 Queue(使用 dispatch_queue_create 函數(shù)), 前面說過攒巍,Queue 是一個抽象概念嗽仪,只是簡單的保存 task 而已荒勇,最終 task 還是要在 GCD Thread Pool 中完成的柒莉。
目標(biāo)隊列 Target Queue
之前講過,task 最終是要從 Queue 中放到線程池中執(zhí)行的沽翔。
其實還有一種情況兢孝,就是 task 可以從一個 Queue 中放到另一個 Queue 中。
需要設(shè)置當(dāng)前 Queue 的 TargetQueue仅偎。
了解了這個概念跨蟹,就能很清楚的明白上面的圖了。
為了更加清楚的闡述這張圖的表達(dá)意圖橘沥,可以從這幾條線說起:
S1 -> Main Queue
MainQueue 這個隊列中的 task 最終都會放到主線程上執(zhí)行窗轩。如果所示,MainQueue 是指向 Main Thread座咆。
也就是說痢艺,如果自定義隊列時,如果這個自定義串行隊列的 Target Queue 是 Main Queue介陶,那么這些 task 將都會放在主線程執(zhí)行堤舒。
S3 -> Default Priority Queue
這里的意思很簡單,自定義隊列的默認(rèn) Target Queue 就是 Default Priority Queue哺呜,這也就是 Objc 所解釋的 在自定義隊列中被調(diào)度的所有 block 最終都將被放入到系統(tǒng)的全局隊列中和線程池中
舌缤。
在 S3 隊列中的任務(wù),會一個接著一個地放入到 Global Queue 中某残,然后被執(zhí)行国撵。在前一個 task 完成之后,才會繼續(xù)下一個 task玻墅。
C2 -> Default Priority Queue
同上介牙,不過這里,會一咕嚕的將 C2 中的 task 往 Global Queue 中放椭豫,不用管上一個 task 是否完成耻瑟。
S2 -> S3
Serial Queue 的 target queue 同樣是 Serial Queue
C1 + S4 -> C2
C1 的 Concurrent Queue 的 target queue = Concurrent Queue
這個就比較高級了旨指。
在這個模式下,S4 中的 task 串行喳整,C1 中的 task 并行谆构。
但是最終它們這些任務(wù)都放在一個并發(fā)隊列中。
最后
以上是個人對于 GCD 的一些見解框都,如有描述不對搬素,還請及時指正。