GCD(Grand Central Dispatch)應該是我們開發中最常用到的多線程解決方案,是蘋果公司專門為多核的並行運算提出的解決方案,是基於C語言的,提供了很多非常強大的函數。 GCD的優勢 1.會自動利用更多的CPU內核(從iPhone4s開始是雙核,iPhone7系列是4核)。 2.會自 ...
GCD(Grand Central Dispatch)應該是我們開發中最常用到的多線程解決方案,是蘋果公司專門為多核的並行運算提出的解決方案,是基於C語言的,提供了很多非常強大的函數。
GCD的優勢
1.會自動利用更多的CPU內核(從iPhone4s開始是雙核,iPhone7系列是4核)。
2.會自動管理線程的創建、生命周期、銷毀等,不需要寫一句關於線程的代碼。
3.將任務添加到隊列中,GCD會自動從隊列中將任務取出,放到對應的線程中執行。
進程與線程
1.簡單點說一個APP就是一個進程,例如微信、迅雷都分別是一個進程。
2.一個進程可以擁有多條線程。當我們打開APP時系統會自動幫我們創建一條主線程,當我們要讓APP乾點別的事時,例如刷新數據,就要開啟一條子線程來向伺服器請求數據,所以一個進程可以擁有多條線程。(並不是讓APP乾什麼事,都會開啟子線程,這裡只是為瞭解釋方便,才這麼說的。)
隊列(queue)
隊列就是用來存放任務的,任務就是我們讓APP乾的事,例如下載圖片,刷新數據等,都是任務。我們使用GCD,只要把任務放到隊列中就可以了,系統會自動幫我們創建線程,調度任務。任務的調度原則遵行FIFO原則,就是哪個任務先放進隊列中,就先執行。隊列分為串列隊列,和並行(併發)隊列。
1.串列隊列 : 就是隊列里的任務必須一個一個往下執行。例如我們要執行A、B、C 三個任務,我們把這三個任務放到串列隊列中,必須是A執行完,B才執行,B執行完C才執行。
創建串列隊列有兩種方法:
(1)自定義隊列
代碼:
// 創建串列隊列
dispatch_queue_t queue = dispatch_queue_create("doujiangyoutiao", DISPATCH_QUEUE_SERIAL);
// 添加任務A
dispatch_async(queue, ^{
NSLog(@"執行任務A");
});
// 添加任務B
dispatch_async(queue, ^{
NSLog(@"執行任務B");
});
// 添加任務C
dispatch_async(queue, ^{
NSLog(@"執行任務C");
});
日誌
2016-11-04 14:00:06.546 TTTTTTTTTT[11059:128030] 執行任務A
2016-11-04 14:00:06.546 TTTTTTTTTT[11059:128030] 執行任務B
2016-11-04 14:00:06.547 TTTTTTTTTT[11059:128030] 執行任務C
1)“doujiangyoutiao”是這個隊列的名字;
2)DISPATCH_QUEUE_SERIAL表示創建的是一條串列對列。
(2)主隊列
dispatch_queue_t queue =dispatch_get_main_queue();
得到主隊列,主隊列是串列隊列,主隊列中的任務預設都在主線程中執行。
2.並行隊列:就是隊列里的任務可以一齊執行。還是舉執行A、B、C 三個任務的例子。我們把三個任務放到並行隊列中,這三個任務可以一起執行,所以不一定誰先下載完。串列隊列里一定是A先下載完。
代碼:
- (void)viewDidLoad {
[super viewDidLoad];
// 創建並行隊列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 添加任務A
dispatch_async(queue, ^{
NSLog(@"執行任務A");
});
// 添加任務B
dispatch_async(queue, ^{
NSLog(@"執行任務B");
});
// 添加任務C
dispatch_async(queue, ^{
NSLog(@"執行任務C");
});
}
每次列印的日誌應該都不一樣,有興趣可以多試幾次。
2016-11-04 14:09:03.871 TTTTTTTTTT[11356:131391] 執行任務B
2016-11-04 14:09:03.871 TTTTTTTTTT[11356:131393] 執行任務C
2016-11-04 14:09:03.871 TTTTTTTTTT[11356:131390] 執行任務A
創建並行隊列有兩種方法:
(1)看上面代碼得到全局並行隊列,不需要我們創建,我們一般用這個。第一個參數表示這個隊列的優先順序
(DISPATCH_QUEUE_PRIORITY_HIGH、DISPATCH_QUEUE_PRIORITY_DEFAULT、DISPATCH_QUEUE_PRIORITY_LOW、DISPATCH_QUEUE_PRIORITY_BACKGROUND),用第二個就可以。第二個參數還沒開發出來,沒有用,預設寫0即可。
(2)自定義隊列
dispatch_queue_t queue=dispatch_queue_create("fuhang",DISPATCH_QUEUE_CONCURRENT);
"fuhang"為併發隊列的名字,後面表示創建的隊列為並行隊列。
註意:
- 併發隊列里的任務一定會一起執行嘛?
答:肯定不會啊。如果併發隊列里有100個任務,一起執行就得創建100條線程,那不得累死CPU啊!任務少了會一起執行,任務多了對先一起執行一部分。 - 線程併發???
答:錯。串列併發是形容隊列的!!!線程沒有,線程里的任務都是一個一個的往下執行,不可能多個任務一起執行。
同步和非同步
同步:會堵塞當前線程,隊列里的任務執行完,任務所在的線程才會往下執行。其實說白了就是插隊。
dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
第一個參數是隊列,第二個參數是要往隊列里添加的任務。
非同步:不會堵塞當前線程。
dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
同上。
同步和非同步就是用來判斷是否要在當前線程的基礎上創建新的線程。同步不會創建新的線程,隊列里的任務在當前線程中執行,所以會堵塞當前線程。但是非同步也不是一定會創建新的線程,這要根據CPU的使用情況來看,但是大多數情況會創建一個線程。