GCD屬於系統及的線程管理,功能很強大,比上兩次我們分享的Operation
要強大。有不少老前輩們已經創造了很是很是多的資料介紹GCD,由於你們都是把GCD放在了多線程內容分享的最開始,因此致使好多好多理論知識都被放在了GCD部分。git
哈哈~幸虧非典型技術宅英明神武的錯峯出行,把一些基礎概念放在了上兩篇文章裏面。極大的減輕了這篇文章的閱讀負擔。github
既然前人都早了辣麼多輪子,俺就不想再多介紹一些基礎理論知識了。反正碼再多的字,只會讓你們馬上立刻關掉這篇文章。並且上一篇關於Operation的閱讀量就明顯不高,看來你們不喜歡看啊。。。面試
那就容我偷偷懶嘛~重點仍是分享一些代碼吧。bash
不是說理論知識不重要啊,面試全都問這個。並且理論知識直接影響到對技術的理解深度,決定能在這條路上走多遠。是會成爲某個領域的大牛,仍是隻是簡單的應用者。網絡
納尼?不是說不說基本概念了嗎?easy~easy~easy~~~只介紹一些那些最最重要的,不瞭解就會影響到閱讀這篇文章的內容啦。多線程
其實GCD和Operation不少地方驚人的類似。廢話,都是多線程,底層都差很少,能不類似嘛!併發
GCD使用只須要兩步:異步
。。。。。。~!@#¥%……&*¥%#@!~@#¥%…… 把大象放進冰箱裏須要幾步?!兩步!打開冰箱門,把大象放進去!宅胖,如今很想抽死你啊!async
確實真的就是這樣的。心裏OS:這只是爲了騙你入門,讓你以爲好簡單。ui
上面說了任務,任務只有兩種方式:同步、異步。
asynchronous
)具有開啓新線程的能力,也具有跳過當前代碼繼續往下執行的能力。synchronous
)不具有開啓新線程的能力,也不具有跳過當前代碼繼續往下執行的能力。名稱 | 開啓新線程的能力 | 跳過當前代碼繼續往下執行的能力 |
---|---|---|
異步 | 有 | 有 |
同步 | NULL |
NULL |
換句話簡單的說,異步任務就是能夠同時開啓多個跑道,同時跑好多輛車。同步就是隻有一條車道,堵死也飛不過去,只能乖乖的等着,一輛接一輛。
任務放入到隊列裏面,會遵循first in first out原則。舉個噁心的例子,就像是拉屎,先吃先拉,後吃後拉。 哈哈~看了這個比方,別打死我~
隊列吶,也只有兩種:串行隊列(Serial Dispatch Queue
)、併發隊列(Concurrent Dispatch Queue
)。
串行隊列(Serial Dispatch Queue
): 讓任務一個接着一個有序的執行,一個任務執行完畢後,再執行下一個任務。
併發隊列(Concurrent Dispatch Queue
) 可讓多個任務同時執行,自動開啓多個線程同時執行多個任務。
咦?有點暈,怎麼感受跟剛纔的任務分類同樣吶?沒錯!就是這樣的。
下面爲了讓你們不要暈菜,咱們把隊列這個中文名字統一都叫作
Queue
,這樣就和OperationQueue
對應起來了,就不會那麼暈了。
Serial Queue
和Concurrent Queue
各自都有一個特殊的Queue
。
主隊列(main queue
):是Serial Queue
中特殊的一種。只能在主線程中進行,而且主隊列裏面的任務,只有當主線程空閒的時候才能被執行。用來刷新UI使用。
全局隊列(global queue
):是Concurrent Queue
中特殊的一種。用來執行耗時操做。
同時,GCD裏面還能夠自定義Queue。
最開始的時候,我們是否是說了,使用GCD就只有兩步:建立任務,把任務放進Queue
裏。
任務有兩種:同步、異步。Queue
加上兩種特殊的(不包括自定義的)一共有四種。來吧,開始排列組合吧。有八種吧。
名稱 | 可以開啓新線程 | 可以跳過當前代碼繼續進行 |
---|---|---|
異步 | 能 | 能 |
同步 | / | / |
Queue |
串行隊列Serial | 並行隊列concurrent | 主隊列main | 全局隊列global |
---|---|---|---|---|
可以多個任務同時執行 | / | 能 | / | 能 |
哈哈哈O(∩_∩)O哈哈~😆😆😆😆
完全暈菜😓
oooO ↘┏━┓ ↙ Oooo ( 踩)→┃你┃ ←(死 ) \ ( →┃√┃ ← ) / _)↗┗━┛ ↖(_/
來吧,直接告訴你結論吧。裏面有幾個特例。
☺ | 串行隊列Serial Queue |
並行隊列concurrent Queue |
主隊列main Queue |
全局隊列global Queue |
---|---|---|---|---|
異步 | 新線程、串行執行 | 新線程、並行執行 | 無新線程、串行執行 | 新線程、並行執行 |
同步 | 無新線程、串行執行 | 無新線程、串行執行 | 無新線程、串行執行 |
看上面這個表,因此若是想要同時作事情,固然不能選同步任務啦。由於它徹底沒能力!搞很差還會形成鎖死。
要想同時作事情,就選concurrent Queue
+ 異步,或者global Queue
+ 異步。 不過人家global Queue
原本就是concurrent Queue
特殊的一種。
若是有多任務,工做中最最省事兒經常使用的就是global Queue
+ 異步。單任務、刷新UI就用main Queue
+ 異步。
上面都沒心思看也不要緊。工做中,若是有多任務,首選
global Queue
+ 異步。單任務、刷新UI就用main Queue
+ 異步。
我滴媽媽~通過上面的分析,最後,最基礎的使用就兩種了。 多任務:global Queue
+ 異步。 單任務、刷新UI就用main Queue
+ 異步。
說實話,我也是第一次這麼大膽的簡化。會不會被大神們拍死?坐等~~~~
global Queue
+ 異步任務/// global Queue + 異步任務
@IBAction func globalAsyn(_ sender: Any) {
//建立一個全局隊列。
//get a global queue
let globalQueue = DispatchQueue.global()
for i in 0...10 {
//使用全局隊列,開啓異步任務。
//use the global queue , run in asynchronous
globalQueue.async {
print("I am No.\(i), current thread name is:\(Thread.current)")
}
}
}
複製代碼
咱們看一下運行的結果,亂序打印的,而且沒有在主線程中。這證實了確實是多個任務沒有按照順序執行。
main Queue
+ 異步任務/// main Queue + 異步任務
@IBAction func mainAsyn(_ sender: Any) {
//建立一個主隊列
//get a main queue
let mainQueue = DispatchQueue.main
for i in 0...10 {
//使用主隊列,開啓異步任務
//use the main queue, run in asynchronous
mainQueue.async {
print("I am No.\(i), current thread name is:\(Thread.current)")
}
}
}
複製代碼
咱們看一下運行的結果,確實是順序打印的。而且都執行在了主線程中。
需求:異步下載一張圖片,下載完成後顯示在UI界面
實現後的效果圖:
思路:
global Queue
+異步,用來下載圖片。由於過程可能很耗時。main Queue
+異步,把下載的圖片賦值,刷新UI。這個小Demo其實也實現了線程間通信。
@IBAction func asynDownloadImage(_ sender: Any) {
let imageVC = ImageVC()
DispatchQueue.global().async {
if let url = URL.init(string: "https://placebeard.it/355/140") {
do {
let imageData = try Data(contentsOf: url)
let image = UIImage(data: imageData)
//由於宅胖家網絡很好,爲了模擬網絡很耗時,就用了延時加載。
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + DispatchTimeInterval.seconds(2), execute: {
imageVC.imageView.image = image
imageVC.imageView .sizeToFit()
})
} catch {
print(error)
}
}
}
navigationController?.pushViewController(imageVC, animated: true)
}
複製代碼
DispatchQoS.QoSClass
是在Swift中封裝的關於描述服務質量的類。
這個在Operation
裏面也見到過,級別越高,就會給分配的資源越多。可是並非嚴格按照級別的高低來執行的。
這是一個枚舉值:
public enum QoSClass {
case background //後臺默默執行,The background quality of service class.
case utility //通用的,The utility quality of service class.
case `default` //默認值,The default quality of service class.
case userInitiated //用戶發起的,The user-initiated quality of service class.
case userInteractive //用來執行用戶交互,The user-interactive quality of service class.
case unspecified //沒啥重要事情,The absence of a quality of service class.
public init?(rawValue: qos_class_t)
public var rawValue: qos_class_t { get }
}
複製代碼
看到上面的枚舉值,也大概能猜出來優先級的高低了。和界面相關的、用戶的確定是高的,後臺默默執行的確定是低的。
從高到低的順序分別是:userInteractive
-> userInitiated
-> default
-> utility
-> background
-> unspecified
最基本的基礎基本上就到這裏了。掂量了一下,還有調度組、信號量、阻塞等等都還沒寫。這時候發現一篇寫完GCD基礎貌似不太現實,又不想一篇文章過長,那就拆開吧。下次再說。
最後,全部的代碼都放在這裏了:gitHub 下載後給顆Star吧~ 麼麼噠~(~o ̄3 ̄)~ 愛大家~
祝各位新春快樂~!~!