文章分享至個人我的技術博客: https://cainluo.github.io/15019074509183.htmlhtml
在前面一篇文章裏, 咱們大概知道了GCD
是個什麼概念, 也知道了如何建立隊列, 建立任務, 但前面的都只是理念, 估計有不少人不喜, 要開始噴我了, 這才咱們來用代碼實踐實踐, 若是沒有看過上一篇的, 能夠去玩轉iOS開發:iOS中的GCD開發(一)看看.git
轉載聲明:如須要轉載該文章, 請聯繫做者, 而且註明出處, 以及不能擅自修改本文.github
這裏咱們就須要建立一個工程, 而後試試水:vim
- (void)syncQueueConcurrent {
NSLog(@"開始執行任務");
dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(queue, ^{
NSLog(@"第一個任務當前線程爲: %@", [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"第二個任務當前線程爲: %@", [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"第三個任務當前線程爲: %@", [NSThread currentThread]);
});
NSLog(@"結束執行任務");
}
複製代碼
2017-08-05 15:03:55.567 GCD-Example[14007:7612071] 開始執行任務
2017-08-05 15:03:55.567 GCD-Example[14007:7612071] 第一個任務當前線程爲: <NSThread: 0x608000067340>{number = 1, name = main}
2017-08-05 15:03:55.567 GCD-Example[14007:7612071] 第二個任務當前線程爲: <NSThread: 0x608000067340>{number = 1, name = main}
2017-08-05 15:03:55.568 GCD-Example[14007:7612071] 第三個任務當前線程爲: <NSThread: 0x608000067340>{number = 1, name = main}
2017-08-05 15:03:55.568 GCD-Example[14007:7612071] 結束執行任務
複製代碼
main
, 並且線程數只有1
.Log
, 從執行順序上咱們能夠知道, 並行隊列+同步執行
是一個任務一個任務的去執行的.接下來咱們看看並行隊列+異步執行
的組合:bash
- (void)asyncQueueConcurrent {
NSLog(@"開始執行任務");
dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"第一個任務當前線程爲: %@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"第二個任務當前線程爲: %@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"第三個任務當前線程爲: %@", [NSThread currentThread]);
});
NSLog(@"結束執行任務");
}
複製代碼
2017-08-05 15:08:40.069 GCD-Example[14052:7619255] 開始執行任務
2017-08-05 15:08:40.070 GCD-Example[14052:7619255] 結束執行任務
2017-08-05 15:08:40.070 GCD-Example[14052:7619380] 第三個任務當前線程爲: <NSThread: 0x60800026a640>{number = 5, name = (null)}
2017-08-05 15:08:40.070 GCD-Example[14052:7619363] 第一個任務當前線程爲: <NSThread: 0x60800026a5c0>{number = 3, name = (null)}
2017-08-05 15:08:40.070 GCD-Example[14052:7619362] 第二個任務當前線程爲: <NSThread: 0x60000026bb00>{number = 4, name = (null)}
複製代碼
並行隊列+異步執行
的組合除了在主隊列
上執行, 還會另外開啓多幾條線程來並行執行任務.繼續下一個串行隊列+同步執行
組合:微信
- (void)syncQueueSerial {
NSLog(@"開始執行任務");
dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
NSLog(@"第一個任務當前線程爲: %@", [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"第二個任務當前線程爲: %@", [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"第三個任務當前線程爲: %@", [NSThread currentThread]);
});
NSLog(@"結束執行任務");
}
複製代碼
2017-08-05 15:16:21.723 GCD-Example[14119:7628753] 開始執行任務
2017-08-05 15:16:21.723 GCD-Example[14119:7628753] 第一個任務當前線程爲: <NSThread: 0x6080000794c0>{number = 1, name = main}
2017-08-05 15:16:21.724 GCD-Example[14119:7628753] 第二個任務當前線程爲: <NSThread: 0x6080000794c0>{number = 1, name = main}
2017-08-05 15:16:21.724 GCD-Example[14119:7628753] 第三個任務當前線程爲: <NSThread: 0x6080000794c0>{number = 1, name = main}
2017-08-05 15:16:21.724 GCD-Example[14119:7628753] 結束執行任務
複製代碼
串行隊列+同步執行
組合是一個一個任務來執行的, 都是在主隊列中完成, 並無開啓新線程.Log
, 而後任務都是按個添加, 最後在執行結束Log
.繼續串行隊列 + 異步執行
:異步
- (void)asyncQueueSerial {
NSLog(@"開始執行任務");
dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
NSLog(@"第一個任務當前線程爲: %@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"第二個任務當前線程爲: %@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"第三個任務當前線程爲: %@", [NSThread currentThread]);
});
NSLog(@"結束執行任務");
}
複製代碼
2017-08-05 17:32:06.723 GCD-Example[14279:7669095] 開始執行任務
2017-08-05 17:32:06.723 GCD-Example[14279:7669095] 結束執行任務
2017-08-05 17:32:06.723 GCD-Example[14279:7669192] 第一個任務當前線程爲: <NSThread: 0x60800006ee00>{number = 3, name = (null)}
2017-08-05 17:32:06.724 GCD-Example[14279:7669192] 第二個任務當前線程爲: <NSThread: 0x60800006ee00>{number = 3, name = (null)}
2017-08-05 17:32:06.724 GCD-Example[14279:7669192] 第三個任務當前線程爲: <NSThread: 0x60800006ee00>{number = 3, name = (null)}
複製代碼
串行隊列
, 因此這裏的任務仍是一個接着一個來執行的.Log
和結束Log
, 最後才執行任務, 能夠說明, 這裏的任務並非一會兒就開始執行的, 是須要將任務都添加到隊列裏, 而後纔開始同步執行.主隊列是GCD
自帶的一種特殊的隊列, 這裏有兩點須要注意一下:async
主隊列
裏執行的任務都會放到主線程
裏執行.dispatch_get_main_queue()
獲取主隊列.說那麼多不如直接來段代碼:ui
- (void)syncMainQueue {
NSLog(@"開始執行任務");
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync(queue, ^{
NSLog(@"第一個任務當前線程爲: %@", [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"第二個任務當前線程爲: %@", [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"第三個任務當前線程爲: %@", [NSThread currentThread]);
});
NSLog(@"結束執行任務");
}
複製代碼
2017-08-05 17:56:24.607 GCD-Example[14437:7689741] 開始執行任務
複製代碼
當咱們運行的時候發現異常了, 斷言在執行完開始Log
以後不動了, 爲何咧?spa
其實這是由於咱們在ViewDidload
方法裏執行了[self syncMainQueue];
方法, 咱們都知道, 同步執行是一個一個任務去執行的.
但主線還在執行[self syncMainQueue];
的時候, 咱們又往主線程裏塞任務, 這個時候就會出現異常現象, 咱們稱之爲卡線程
.
若是要解決的話, 咱們就須要在ViewDidload
裏改善一下方案:
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
[self syncMainQueue];
});
}
複製代碼
2017-08-05 18:03:33.209 GCD-Example[14492:7698292] 開始執行任務
2017-08-05 18:03:33.214 GCD-Example[14492:7698172] 第一個任務當前線程爲: <NSThread: 0x600000066340>{number = 1, name = main}
2017-08-05 18:03:33.215 GCD-Example[14492:7698172] 第二個任務當前線程爲: <NSThread: 0x600000066340>{number = 1, name = main}
2017-08-05 18:03:33.216 GCD-Example[14492:7698172] 第三個任務當前線程爲: <NSThread: 0x600000066340>{number = 1, name = main}
2017-08-05 18:03:33.216 GCD-Example[14492:7698292] 結束執行任務
複製代碼
唔, 醬紫改造就能夠順利的執行完任務了, 這裏還須要提多兩點:
ViewDidload
用的是並行+異步
的組合去改善的, 但這不會影響到主隊列裏的任務執行順序, 也不會開啓新線程.最後一個組合主隊列+異步執行
:
- (void)asyncMainQueue {
NSLog(@"開始執行任務");
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_async(queue, ^{
NSLog(@"第一個任務當前線程爲: %@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"第二個任務當前線程爲: %@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"第三個任務當前線程爲: %@", [NSThread currentThread]);
});
NSLog(@"結束執行任務");
}
複製代碼
2017-08-05 18:08:16.059 GCD-Example[14537:7704614] 開始執行任務
2017-08-05 18:08:16.059 GCD-Example[14537:7704614] 結束執行任務
2017-08-05 18:08:16.064 GCD-Example[14537:7704614] 第一個任務當前線程爲: <NSThread: 0x608000261700>{number = 1, name = main}
2017-08-05 18:08:16.064 GCD-Example[14537:7704614] 第二個任務當前線程爲: <NSThread: 0x608000261700>{number = 1, name = main}
2017-08-05 18:08:16.065 GCD-Example[14537:7704614] 第三個任務當前線程爲: <NSThread: 0x608000261700>{number = 1, name = main}
複製代碼
異步執行
, 具有了開啓新線程的能力, 可是因爲這是主隊列, 因此全部的任務都是在主線程中, 任務也是一個接着一個執行的.Log
, 結束Log
, 最後再執行主隊列裏的任務, 這裏咱們就能夠知道, 任務並非立刻就執行的, 而是把全部任務都添加到隊列裏以後, 再執行.學完以後, 咱們就能夠愉快的和GCD
玩耍了, 隊列, 任務神馬的, 不再用擔憂了.
項目地址: https://github.com/CainRun/iOS-Project-Example/tree/master/GCD-Example