1、概念回顧程序員
一、GCD全稱 Grand Central Dispatch ,是純C語言,提供了很是多強大的函數,來進行系統線程的管理。併發
二、優點:GCD是蘋果公司爲多核的並行運算提出的解決方案。GCD會自動利用更多的CPU內核,會自動管理線程的生命週期(建立線程、調度任務、銷燬線程),程序員只須要告訴GCD想要執行什麼任務,不須要編寫任何線程管理代碼。異步
三、GCD的兩個核心:async
(1)隊列:GCD會從隊列中取出任務,按照不一樣狀況,放到對應的線程中執行,遵循FIFO原則。ide
隊列共分有四種:函數
a、串行 :任務一個接一個的執行。spa
b、併發 :可讓任務同時執行,就是開啓多個線程執行任務。線程
c、全局 :本質就是併發隊列,區別:沒有名稱,不可跟蹤;在MRC中釋放次數不同。code
經過函數 dispatch_get_global_queue(<#long identifier#>, <#unsigned long flags#>)得到,第一個參數是優先級,第二個是預留(無用),通常兩者都設爲0。blog
d、主隊列 :在主線程中順序執行,有死鎖現象(主隊列同步執行的狀況)。
(2)任務:就是要處理的事情。
任務處理(操做)方式有兩種
a、同步 :在當前線程執行,不開闢新的線程。
b、異步 :在新的線程中執行任務,能夠開啓新的一條或多條線程。
四、隊列和任務執行方式的組合
2、實驗觀察線程管理狀況
各類狀況都寫在viewDidLoad中,須要時打開註釋,方便比較和查閱
- (void)viewDidLoad { [super viewDidLoad]; //串行隊列 dispatch_queue_t serial = dispatch_queue_create("serial", DISPATCH_QUEUE_SERIAL); //並行隊列 dispatch_queue_t concurrent = dispatch_queue_create("concurrent", DISPATCH_QUEUE_CONCURRENT); //建立block1 dispatch_block_t block1 = ^{ //特地將第一個任務延遲一秒,用來觀察執行順序 [NSThread sleepForTimeInterval:1]; NSLog(@" block1 ==> %@",[NSThread currentThread]); }; //建立block2 dispatch_block_t block2 = ^{ NSLog(@" block2 ==> %@",[NSThread currentThread]); }; #pragma mark - 串行同步 :在當前線程,FIFO順序執行任務 // dispatch_sync(serial, block1); // dispatch_sync(serial, block2); #pragma mark - 串行異步 :新建一個線程,出隊列後按FIFO順序執行 // dispatch_async(serial, block1); // dispatch_async(serial, block2); #pragma mark - 併發同步 :在當前線程,出隊列後順序執行 // dispatch_sync(concurrent, block1); // dispatch_sync(concurrent, block2); #pragma mark - 併發異步 :建立N個新線程,出隊列後隨機(同時)執行 // dispatch_async(concurrent, block1); // dispatch_async(concurrent, block2); #pragma mark - 全局同步 :相似併發同步,全局隊列是經過函數得到的 // dispatch_sync(dispatch_get_global_queue(0, 0), block1); // dispatch_sync(dispatch_get_global_queue(0, 0), block2); #pragma mark - 全局異步 :相似併發異步 // dispatch_async(dispatch_get_global_queue(0, 0), block1); // dispatch_async(dispatch_get_global_queue(0, 0), block2); #pragma mark - 主隊列同步(死鎖):主線程等待主隊列中任務執行完畢(一直掛起,不是空閒)後面的代碼都沒法運行,然而主隊列中的任務又在等待主線程空閒(也一直掛起,等待着主線程能夠閒下來),全部二者相互等待,造成死鎖。 // dispatch_sync(dispatch_get_main_queue(), block1); // dispatch_sync(dispatch_get_main_queue(), block2); #pragma mark - 主隊列同步(解死鎖):加上一個全局異步,這樣主線程不會卡住,主線程能夠執行完它的代碼,回過頭來(此時空閒了),處理主隊列裏面的任務,不會鎖死。 // dispatch_async(dispatch_get_global_queue(0, 0), ^{ // NSLog(@"我是解鎖的開始,此時線程 ===》%@ ",[NSThread currentThread]); // dispatch_sync(dispatch_get_main_queue(), block1); // dispatch_sync(dispatch_get_main_queue(), block2); // NSLog(@"死鎖被解開了!!%@ ",[NSThread currentThread]); // }); #pragma mark - 主隊列異步 : 主線程空閒時才執行主隊列中的內容,出隊列順序執行 // dispatch_async(dispatch_get_main_queue(), block1); // dispatch_async(dispatch_get_main_queue(), block2); NSLog(@" (主線程)我是寫在程序最後的 =====》 end"); }
貼上幾種組合的執行結果圖(不是全部)
一、串行異步
二、併發同步
三、主隊列同步 (解開死鎖的狀況)
四、主隊列異步
3、總結
GCD管理線程,功能強大:有沒有新線程看是否同步——異步;有沒有順序執行看是否串行——並行。
還有多種線程管理的方式:pthread、NSThread、NSOperation(NSInvocationOperation、NSBlockOperation),各有優缺點,以及使用的場景,之後再作討論。