通過 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===
//參數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、併發隊列只在異步函數中有效(如果想要一個任務異步執行,必須在併發隊列中使用異步函數執行)