GCD中各類隊列和任務執行方式的組合

 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),各有優缺點,以及使用的場景,之後再作討論。

相關文章
相關標籤/搜索