文章分享至個人我的技術博客: https://cainluo.github.io/15019284409430.htmlhtml
上一章, 咱們瞭解到了GCD
裏的一些隊列和任務的知識, 也實踐了一下, 同時咱們也對主隊列的一些小狀況瞭解了一下, 好比上一章講到的卡線程的問題, 若是沒有看的朋友能夠去看看玩轉iOS開發:iOS中的GCD開發(二)回顧一下.git
這一章, 咱們來說講關於GCD
的一些其餘小知識.github
轉載聲明:如須要轉載該文章, 請聯繫做者, 而且註明出處, 以及不能擅自修改本文.vim
在咱們平常的iOS
開發裏, 咱們通常是會在主線程裏刷新UI
, 好比: 處理按鈕的點擊事件, 滾動視圖, 拖拽視圖等等操做.安全
但其餘比較耗時的, 咱們都會放在其餘線程裏進行操做, 好比: 上傳/下載圖片, 上傳/下載文件等比較耗時的操做.微信
但這裏還須要配合一下主線程來進行操做一番, 好比咱們下載完圖片以後, 須要回到主線程中刷新UI
, 這時候咱們就須要用到GCD
之間的通訊啦.app
不懂? 那咱們就來看看代碼唄, 這裏爲了和上一章的工程重複, 我就新建過另外一個工程, 取名爲GCD-Up-Example
, 機智如我~異步
- (void)gcdCommunication {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
for (NSInteger i = 0; i < 5; i++) {
NSLog(@"第%ld次任務的主線程爲: %@", i, [NSThread currentThread]);
}
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"回到主線程, 該線程爲: %@", [NSThread currentThread]);
});
});
}
複製代碼
2017-08-05 18:47:11.942 GCD-Up-Example[15176:7745714] 第0次任務的主線程爲: <NSThread: 0x60000006bb80>{number = 3, name = (null)}
2017-08-05 18:47:11.942 GCD-Up-Example[15176:7745714] 第1次任務的主線程爲: <NSThread: 0x60000006bb80>{number = 3, name = (null)}
2017-08-05 18:47:11.943 GCD-Up-Example[15176:7745714] 第2次任務的主線程爲: <NSThread: 0x60000006bb80>{number = 3, name = (null)}
2017-08-05 18:47:11.943 GCD-Up-Example[15176:7745714] 第3次任務的主線程爲: <NSThread: 0x60000006bb80>{number = 3, name = (null)}
2017-08-05 18:47:11.944 GCD-Up-Example[15176:7745714] 第4次任務的主線程爲: <NSThread: 0x60000006bb80>{number = 3, name = (null)}
2017-08-05 18:47:11.948 GCD-Up-Example[15176:7745541] 回到主線程, 該線程爲: <NSThread: 0x60000006a1c0>{number = 1, name = main}
複製代碼
有這麼一個場景, 當咱們須要進行異步操做兩組數據時, 要求執行完第一組以後, 才能執行第二組, 那這個咋辦咧?async
在GCD
當中, 有一個方法能夠解決這種需求, 也就是所謂的柵欄方法
也稱爲屏障
, 如今咱們來擼一下:學習
- (void)gcdBarrier {
dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"第一次任務的主線程爲: %@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"第二次任務的主線程爲: %@", [NSThread currentThread]);
});
dispatch_barrier_async(queue, ^{
NSLog(@"第一次任務, 第二次任務執行完畢, 繼續執行");
});
dispatch_async(queue, ^{
NSLog(@"第三次任務的主線程爲: %@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"第四次任務的主線程爲: %@", [NSThread currentThread]);
});
}
複製代碼
2017-08-05 19:00:44.494 GCD-Up-Example[15252:7757142] 第一次任務的主線程爲: <NSThread: 0x60000007d580>{number = 3, name = (null)}
2017-08-05 19:00:44.494 GCD-Up-Example[15252:7757144] 第二次任務的主線程爲: <NSThread: 0x60800007bb00>{number = 4, name = (null)}
2017-08-05 19:00:44.494 GCD-Up-Example[15252:7757144] 第一次任務, 第二次任務執行完畢, 繼續執行
2017-08-05 19:00:44.495 GCD-Up-Example[15252:7757144] 第三次任務的主線程爲: <NSThread: 0x60800007bb00>{number = 4, name = (null)}
2017-08-05 19:00:44.495 GCD-Up-Example[15252:7757142] 第四次任務的主線程爲: <NSThread: 0x60000007d580>{number = 3, name = (null)}
複製代碼
柵欄方法
以後, 纔會繼續執行以後的任務.有時候, 須要一些延遲操做的場景, 那咋辦咧? 放心~GCD
也有提供這樣子的方法, 而且延遲多少時間是由你說了算:
- (void)gcdAfter {
NSLog(@"我是一個路人");
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"2秒後執行了.");
});
}
複製代碼
2017-08-05 19:07:20.039 GCD-Up-Example[15340:7766123] 我是一個路人
2017-08-05 19:07:22.225 GCD-Up-Example[15340:7766123] 2秒後執行了.
複製代碼
2.0
, 這就是設置時間了.有時候, 咱們須要建立一個類, 而這個類的某個方法只能夠執行一次, 好比建立一個單例, 怎麼用GCD
解決呢?
既然可以提到這個問題, 那GCD
確定也會提供對方的方法嘛, 是吧~
- (void)gcdOne {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 這裏寫只執行一次的任務就行了, 默認是線程安全, 因此不用擔憂
});
}
複製代碼
在GCD
當中, 也有一個相似for
的遍歷方法, 和for
不一樣, 它幾乎是同時遍歷的.
- (void)gcdApply {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(5, queue, ^(size_t index) {
NSLog(@"執行第%ld任務, 當前線程爲: %@", index, [NSThread currentThread]);
});
}
複製代碼
2017-08-05 20:36:08.389 GCD-Up-Example[15555:7794146] 執行第0任務, 當前線程爲: <NSThread: 0x608000074840>{number = 1, name = main}
2017-08-05 20:36:08.389 GCD-Up-Example[15555:7794186] 執行第1任務, 當前線程爲: <NSThread: 0x60800007e2c0>{number = 3, name = (null)}
2017-08-05 20:36:08.389 GCD-Up-Example[15555:7794184] 執行第2任務, 當前線程爲: <NSThread: 0x60800007e200>{number = 4, name = (null)}
2017-08-05 20:36:08.389 GCD-Up-Example[15555:7794183] 執行第3任務, 當前線程爲: <NSThread: 0x60800007e300>{number = 5, name = (null)}
2017-08-05 20:36:08.389 GCD-Up-Example[15555:7794146] 執行第4任務, 當前線程爲: <NSThread: 0x608000074840>{number = 1, name = main}
複製代碼
在某個場景下, 咱們須要同時異步執行兩個耗時的任務, 而且在執行完成後直接回到主線程, 這個怎麼作呢?
在GCD
中, 有一個叫作隊列組的東西(Queue Group)
, 它就能夠知足咱們這個場景需求了.
- (void)gcdQueueGroup {
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_async(group,
queue,
^{
// 執行第一個耗時的任務
});
dispatch_group_async(group,
queue,
^{
// 執行第二個耗時的任務
});
dispatch_group_notify(group,
dispatch_get_main_queue(),
^{
// 回到主線程
});
}
複製代碼
GCD
的一些經常使用知識基本到這裏, 基本上已經哦了, 若是你還要更深刻的去了解的話, 能夠去GCD官方文檔裏查找一下你所須要的資料.
再多說一句話, 學習理論知識當然重要, 但要和實際開發使用掛鉤, 否則光學不用, 等於空.
項目地址: https://github.com/CainRun/iOS-Project-Example/tree/master/GCD-Up-Example