常用的
- dispatch_get_main_queue 主隊列
- dispatch_get_global_queue 全部并發的隊列
通常的基本用法:
dispatch_async(dispatch_get_global_queue(0, 0), ^{
// 執行 耗時的任務
dispatch_async(dispatch_get_main_queue(), ^{
// 執行完成后,回到主線程 刷新UI
});
});
主隊列就不介紹了,直接說全局隊列
dispatch_get_global_queue
有兩個參數,第二個沒什么用,蘋果留給以后的擴展,第一個參數就是優先級了,在NSThread里面有設置優先級的屬性Priority
,在GCD里當然也是有的。
首先:
可以看得出
dispatch_get_global_queue
是同時運行的,順序也是不確定的。說明它是一個全局并發的隊列再看它的線程id,是三個不同的id,所以說明是創建了三個線程,然后異步執行。
優先級:
全局隊列第一個參數:
設置優先級后的效果
我們給2設置了最高級別,但是卻是3先開始的,但是結束的時候是2先結束的,所以說這個優先級設置也是有一定概率的,一般情況下優先級高的會比優先級低的先執行完。
但是 如果線程執行的任務復雜度不同,那么就會出現混亂的問題,因為還是為了保持一個順序的話,那么我們就需要用到串行的隊列了。GCD也給們我提供了串行的隊列
串行隊列,執行是有順序的。
可以看的出來我們自己創建的隊列queue 默認是串行的。兩個參數,第一個是唯一標識,第二個就是設置 串行、并行。NULL默認為串行的。
看打印出來的結果 和 時間,可以看出來是串行的隊列,一個執行完成再執行另一個的。
還有個重點:這是在一個線程里面執行的。不知道大家有沒有看出來,你們看下面的線程id號是一樣的。
參數 第二個參數 兩種:
- DISPATCH_QUEUE_CONCURRENT 并行
- DISPATCH_QUEUE_SERIAL 串行
修改參數后就是并行的隊列,三個線程并發執行。
學了這些,有沒有一些問題呢? 首先呢,對于串行隊列,我們可以在所有任務都完成的時候回到主線程然后去做一些其他的工作,你們有沒有想一個問題:
實際開發中:有這種串行的隊列開發的應用嗎?沒有吧,這樣會阻塞當前線程,造成用戶體驗不好。實際開發中都是并行隊列,異步執行。
那么問題來了:
多個接口并發執行,我想在所有接口都回調完成后刷新UI,怎么做?
兩種解決方法:
- 加入標記位
- GCD的
dispatch_group_t
我們這里講第二種。
GCD的dispatch_group_t
就是為了解決多個接口并發執行,在最后執行完成 給予 回調 的問題的。
為什么呢?因為 它有個 dispatch_group_notify
這個方法,它會在隊列中所有異步線程請求完后 回調?。。【褪沁@么流弊。
代碼就是這樣的,看輸出臺,是不是在所有并發隊列請求完成后回調的?si bu si ?
但是有個問題,不知道大家注意了沒有,我們的notify回調不是在主線程中執行的,它是在系統分配在最后一個完成的隊列中回調提示的。
所以解決辦法就是把notify 方法的第二個參數換成主線程。
上面的不貼了,看效果是不是。
小tips:
因為GCD是自動控制線程的生命周期的,我們不需要關心線程的一些屬性,所以一般主線程的name是main,所以的子線程的name都是null。
那么我們模擬兩個數據請求接口
這時候我們就可以把這兩個請求數據的方法 放入到我們的 異步請求里面了。
看輸出結果,好像跟我們預期的不太一樣啊。在1、2任務剛開始的時候就提示全部完成了,然后刷新UI,刷新完后才真正的完成數據回調處理數據啊。感覺不對啊~~~!!怎么辦?
其實仔細看你會發現,我們的這兩個請求的Block都是異步請求對吧!然后把這兩個異步請求放入到異步請求里面。這樣就形成了異步套異步啊。?。。。。《???外層異步不會持有request,所以外層的兩個異步會瞬間完成,然后我們的dispatch_group_notify
會直接回調完成。但是在內層的請求卻還在進行著。。。。那么我們改成同步group?呵呵告訴你沒有dispatch_group_sync這方法,你自己創造去吧!呵呵噠!
那么怎么解決這樣的問題呢?
- dispatch_group_enter();
- dispatch_group_leave();
這兩個方法。1是在整個異步請求的過程中group持有 2是在異步請求完成后不在持有。所以這兩行代碼的意思就是把這個異步請求放入到group當中。 這樣就和我們預期的效果是一樣的了。
總結:
- dispatch_get_main_queue 主隊列
- dispatch_get_global_queue 全局隊列 有兩個參數,第一個設置優先級,第二個目前沒用。
- dispatch_async 異步執行
dispatch_sync 同步執行 - dispatch_queue_create 創建一個隊列 第一個參數是唯一標識,第二個是優先級。對象是dispatch_queue_t類型。
- dispatch_group_async 異步執行組隊列
dispatch_group_enter 從某時開始持有
dispatch_group_leave 到某時不在持有 - dispatch_group_create 創建一個組 沒有參數,對象是dispatch_group_t類型
- dispatch_group_notify 組內所以隊列完成后 回調。注意,回調的不是在主線程中,需要UI刷新的 比如切到主線程中。
從以上的學習、分析,我們好像根本沒有像NSThread的那種去創建見一個線程,去設置線程的屬性,管理線程的生命周期。對吧!所以說GCD 是不需要去管理線程的。我只要是創建隊列和組,告訴去干什么就可以了。是不是很容易,雖然代碼可讀性差。