iOS-GCD多執行緒
1、GCD基本知識
學習 GCD 之前,先來了解 GCD 中兩個核心概念:任務和佇列。
任務:當前執行的操作,換句話說就是現線上程中執行的那段程式碼,在 GCD 中是放在 block 中的。
任務的執行有兩種方式:同步執行(sync)和非同步執行(async)。兩者的主要區別是:是否等待佇列的任務執行結束,以及是否具備開啟新執行緒的能力。
- 同步執行(sync):
- 同步新增任務到指定的佇列中,需要等待這個佇列排在它之前的任務執行完了之後才會輪到它執行,舉個栗子:你現在在吃飯,這時睡覺的任務新增進來,你只有吃完飯後才能去睡覺。
- 只能在當前執行緒中執行任務,不具備開啟新執行緒的能力。
- 非同步執行(async):
- 非同步新增任務到指定的佇列中,它不會做任何等待,當前佇列任務可以繼續執行。舉個栗子:你現在在吃飯,這時有一個電話打過來,你就可以邊吃飯邊打電話。
- 可以在新的執行緒中執行任務,具備開啟新執行緒的能力。
注意:非同步執行(async)雖然具有開啟新執行緒的能力,但是並不一定會開啟新執行緒。這跟任務所指定的佇列型別有關。
佇列(Dispatch Queue):這裡的佇列指執行任務的等待佇列,即用來存放任務的佇列。佇列是一種特殊的線性表,採用 FIFO(先進先出)的原則,即新任務總是被插入到佇列的末尾,而讀取任務的時候總是從佇列的頭部開始讀取。每讀取一個任務,則從佇列中釋放一個任務。
在 GCD 中有兩種佇列:序列佇列和併發佇列。兩者都符合 FIFO(先進先出)的原則。兩者的主要區別是:執行順序不同,以及開啟執行緒數不同。
- 序列佇列(Serial Dispatch Queue):
- 每次只有一個任務被執行。讓任務一個接著一個地執行。(只開啟一個執行緒,一個任務執行完畢後,再執行下一個任務)
- 併發佇列(Concurrent Dispatch Queue):
- 可以讓多個任務併發(同時)執行。(可以開啟多個執行緒,並且同時執行任務)
注意:併發佇列的併發功能只有在非同步(dispatch_async)函式下才有效
2、GCD基本使用
GCD 的使用步驟其實很簡單,只有兩步。
- 建立一個佇列(序列佇列或併發佇列)
- 將任務追加到任務的等待佇列中,然後系統就會根據任務型別執行任務(同步執行或非同步執行)
//建立序列佇列
dispatch_queue_t serialQueue = dispatch_queue_create("佇列名字", DISPATCH_QUEUE_SERIAL);
//建立併發佇列
dispatch_queue_t concurrentQueue = dispatch_queue_create("佇列名字", DISPATCH_QUEUE_CONCURRENT);
不過一般情況下我們不用自己建立佇列,而是使用系統提供的佇列。
對於序列佇列,GCD 提供了的一種特殊的序列佇列:主佇列(Main Dispatch Queue)。
- 所有放在主佇列中的任務,都會放到主執行緒中執行。
- 可使用
dispatch_get_main_queue()
獲得主佇列。
對於併發佇列,GCD 預設提供了全域性併發佇列(Global Dispatch Queue),其實全域性併發佇列可以當做普通併發佇列使用。
- 可以使用
dispatch_get_global_queue
來獲取。需要傳入兩個引數。第一個引數表示佇列優先順序,一般用DISPATCH_QUEUE_PRIORITY_DEFAULT
。第二個引數暫時沒用,用0
即可。
根據執行方式和佇列型別,我們就有六種組合方式。
區別 | 併發佇列 | 序列佇列 | 主佇列 |
---|---|---|---|
同步(sync) | 沒有開啟新執行緒,序列執行任務 | 沒有開啟新執行緒,序列執行任務 | 主執行緒呼叫:死鎖卡住不執行(注意) 其他執行緒呼叫:沒有開啟新執行緒,序列執行任務 |
非同步(async) | 有開啟新執行緒,併發執行任務(常用) | 有開啟新執行緒(1條),序列執行任務 | 沒有開啟新執行緒,序列執行任務(常用) |
3、GCD 執行緒間的通訊
在iOS開發過程中,我們一般在主執行緒裡邊進行UI介面重新整理,例如:改變控制元件內容、點選、滾動、拖拽等事件。
我們通常把一些耗時的操作放在其他執行緒,比如說圖片下載、檔案上傳等耗時操作。
而當我們有時候在其他執行緒完成了耗時操作時,需要回到主執行緒,那麼就用到了執行緒之間的通訊。
//這是常用用法
dispatch_async(ISGetGlobalQueue, ^{
//非同步執行併發佇列,執行耗時操作
//執行完畢後,非同步執行主佇列
dispatch_async(ISGetMainQueue, ^{
//執行更新UI介面等操作
});
});