iOS GCD(一)

通過 GCD,開發者不用再直接跟線程打交道了,只需要向隊列中添加代碼塊即可,GCD 在後端管理着一個線程池。GCD 不僅決定着你的代碼塊將在哪個線程被執行,它還根據可用的系統資源對這些線程進行管理。這樣可以將開發者從線程管理的工作中解放出來,通過集中的管理線程,來緩解大量線程被創建的問題


先弄清幾個概念

同步:在當前線程中執行,沒有開線程的能力(dispatch_sync)

異步:在新的線程中執行,有開線程的能力(dispatch_async)


串行隊列:任務一個接一個的執行

併發隊列:讓多個任務併發(同時)執行,只有在開啓線程即異步函數(dispatch_async)下有效(例如下面全局隊列同步執行無效)


隊列:有三種隊列

主隊列:是一種串行隊列,能夠保證任務一個接一個的執行,比較特殊的是它是唯一一個可以刷新UI的隊列,所有刷新UI的操作都必須在主隊列中執行,實際應用中是在子線程中執行接收數據的耗時操作,接收完成後再在主線程中刷新UI界面  用 dispatch_get_main_quene() 得到

全局隊列:是一種併發隊列,有四種優先級background default ,low high 用 dispatch_get_global_quene() 得到

自定義隊列:可以是串行隊列也可以是併發隊列(取決於參數)  用disaptch_quene_create()得到


使用:

1、主線程

1️⃣主隊列中使用異步執行

dispatch_queue_t mainQuene = dispatch_get_main_queue();
    NSLog(@"開始執行");
    dispatch_async(mainQuene, ^{
        NSLog(@"%@",[NSThread currentThread]);
        NSLog(@"在主隊列中使用異步執行");
    });
    NSLog(@"結束執行");


執行結果

2016-12-27 10:55:21.482 GCD[932:79002] 開始執行
2016-12-27 10:55:21.483 GCD[932:79002] 結束執行
2016-12-27 10:55:21.491 GCD[932:79002] <NSThread: 0x6000000771c0>{number = 1, name = main}
2016-12-27 10:55:21.491 GCD[932:79002] 在主隊列中使用異步執行



2️⃣主隊列中使用同步執行

dispatch_queue_t mainQuene = dispatch_get_main_queue();
    NSLog(@"開始執行");
    dispatch_sync(mainQuene, ^{
        NSLog(@"在主隊列中使用同步執行");
    });
    NSLog(@"結束執行");
    
這裏會報錯:原因是產生了死鎖 。  這些代碼是在viewDidload中執行中,主隊列是串行隊列,只能一個接一個任務的執行,本身就在執行,這裏添加了一個任務到主隊列,並且是同步執行,造成了互相等待的死鎖


2、全局隊列
1️⃣全局隊列中同步執行

//同步執行不開啓新線程,隊列中的所有任務都是在本身所在隊列中(現在是主隊列)執行,並且是順序執行

dispatch_queue_t globalQuene = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
    
    dispatch_sync(globalQuene, ^{
        NSLog(@"%@",[NSThread currentThread]);
        NSLog(@"1===");
    });
    dispatch_sync(globalQuene, ^{
        NSLog(@"%@",[NSThread currentThread]);
        NSLog(@"2===");
    });
    dispatch_sync(globalQuene, ^{
        NSLog(@"%@",[NSThread currentThread]);
        NSLog(@"3===");
    });
    dispatch_sync(globalQuene, ^{
        NSLog(@"%@",[NSThread currentThread]);
        NSLog(@"4===");
    });

執行結果

2016-12-27 11:17:10.733 GCD[995:90895] <NSThread: 0x60800007c600>{number = 1, name = main}
2016-12-27 11:17:10.733 GCD[995:90895] 1===
2016-12-27 11:17:10.734 GCD[995:90895] <NSThread: 0x60800007c600>{number = 1, name = main}
2016-12-27 11:17:10.734 GCD[995:90895] 2===
2016-12-27 11:17:10.734 GCD[995:90895] <NSThread: 0x60800007c600>{number = 1, name = main}
2016-12-27 11:17:10.734 GCD[995:90895] 3===
2016-12-27 11:17:10.734 GCD[995:90895] <NSThread: 0x60800007c600>{number = 1, name = main}
2016-12-27 11:17:10.734 GCD[995:90895] 4===


2️⃣全局隊列異步執行

//異步執行不開啓新線程,隊列中的任務在開啓的新線程中執行,開啓的線程的數量不定,並且執行的順序也不定

dispatch_queue_t globalQuene = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
    dispatch_async(globalQuene, ^{
        NSLog(@"%@",[NSThread currentThread]);
        NSLog(@"1===");
    });
    dispatch_async(globalQuene, ^{
        NSLog(@"%@",[NSThread currentThread]);
        NSLog(@"2===");
    });
    dispatch_async(globalQuene, ^{
        NSLog(@"%@",[NSThread currentThread]);
        NSLog(@"3===");
    });
    dispatch_async(globalQuene, ^{
        NSLog(@"%@",[NSThread currentThread]);
        NSLog(@"4===");
    });

執行結果
2016-12-27 11:18:55.217 GCD[1012:93021] <NSThread: 0x608000267280>{number = 5, name = (null)}
2016-12-27 11:18:55.217 GCD[1012:93007] <NSThread: 0x608000267340>{number = 3, name = (null)}
2016-12-27 11:18:55.217 GCD[1012:93005] <NSThread: 0x6080002674c0>{number = 6, name = (null)}
2016-12-27 11:18:55.217 GCD[1012:93004] <NSThread: 0x6000002621c0>{number = 4, name = (null)}
2016-12-27 11:18:55.217 GCD[1012:93021] 3===
2016-12-27 11:18:55.217 GCD[1012:93007] 1===
2016-12-27 11:18:55.217 GCD[1012:93005] 4===
2016-12-27 11:18:55.217 GCD[1012:93004] 2===


3、自定義隊列

    //參數1 隊列的名稱,命名規則爲應用名稱id的倒序   參數2 如果是null 則創建的隊列爲串行隊列 如果是DISPATCH_QUEUE_CONCURRENT 則創建的隊列是併發隊列
    dispatch_queue_t currentQuene = dispatch_queue_create("current", DISPATCH_QUEUE_CONCURRENT);
    NSLog(@"開始");
    dispatch_async(currentQuene, ^{
        NSLog(@"當前線程1:%@",[NSThread currentThread]);
    });
    dispatch_async(currentQuene, ^{
        NSLog(@"當前線程2:%@",[NSThread currentThread]);
    });
    dispatch_async(currentQuene, ^{
        NSLog(@"當前線程3:%@",[NSThread currentThread]);
    });
    NSLog(@"結束");
執行結果
2016-12-27 11:37:41.282 GCD[1109:108111] 開始
2016-12-27 11:37:41.282 GCD[1109:108111] 結束
2016-12-27 11:37:41.282 GCD[1109:108148] 當前線程2:<NSThread: 0x600000076900>{number = 4, name = (null)}
2016-12-27 11:37:41.282 GCD[1109:108145] 當前線程1:<NSThread: 0x608000070cc0>{number = 3, name = (null)}
2016-12-27 11:37:41.282 GCD[1109:108162] 當前線程3:<NSThread: 0x608000071840>{number = 5, name = (null)}


總結:

        主隊列             全局隊列        自定義隊列(串行) 自定義隊列(併發)
async(異步)
未開新線程

順序執行
開新線程

異步執行
開新線程

同步執行
開新線程

異步執行
sync(同步)
死鎖
未開新線程

順序執行
未開新線程

順序執行
未開新線程

順序執行


注:

1、在主隊列中不能使用同步執行函數(會產生死鎖)

2、只有異步執行函數才具有開新線程的能力

3、併發隊列只在異步函數中有效(如果想要一個任務異步執行,必須在併發隊列中使用異步函數執行)


發佈了38 篇原創文章 · 獲贊 19 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章