本文的主要內(nèi)容是:
- 什么是GCD
- 了解GCD前,需要了解的基礎(chǔ)知識
- GCD的使用
- 使用注意事項
-GCD學(xué)習(xí)前鋪墊-
什么是GCD
- GCD (Grand Central Dispatch) 是Apple公司開發(fā)的一種技術(shù),它旨在優(yōu)化多核環(huán)境中的并發(fā)操作并取代傳統(tǒng)多線程的編程模式
- GCD是基于C語言的線程管理方案,使用者無需過多參與線程的管理,只需要將想要執(zhí)行的代碼,添加到想要添加的調(diào)度隊列即可
- 在Mac OS X 10.6雪豹中首次推出,并在iOS4.0中引入到了iOS
- GCD主要用在后臺執(zhí)行較慢任務(wù);延遲執(zhí)行任務(wù);以及在后臺任務(wù)中,切換回主線程,更新UI
iOS中常用的其它多線程技術(shù)
pthread:通用于Unix/Linux/Windows的C語言線程管理API,可移植性強(qiáng),但是使用繁瑣,需要使用者管理線程生命周期
NSThread:使用Objective-C實現(xiàn),輕量級的線程管理,但是也需要手動管理線程的生命周期
NSOperation:基于GCD,使用Objective-C實現(xiàn)的面向?qū)ο蟮木€程管理,比GCD更高級,但是處理簡單任務(wù)會比GCD代碼更多
總之,iOS里GCD用的很多
GCD知識鋪墊
競爭&同步:兩個線程搶奪同一個資源,就會競爭,為了防止競爭,一個線程擁有資源的時候,會對資源加鎖,另一個線程就要等待解鎖以后再擁有這個資源,這叫同步。
死鎖:兩個線程互相等待對方釋放資源
主線程&后臺線程:主線程也叫前臺線程,程序啟動的默認(rèn)線程,操作UI的線程。后臺線程,即非主線程,用于不影響主線程的完成一些任務(wù)
并行&串行:并行,就是幾個任務(wù)一起完成。串行,就是幾個任務(wù)一個接著一個完成。
同步&異步:同步執(zhí)行線程,等待新線程執(zhí)行完以后,再繼續(xù)執(zhí)行當(dāng)前線程,很少用到。異步執(zhí)行線程,在執(zhí)行新線程的同時,繼續(xù)執(zhí)行當(dāng)前線程,常用。
-GCD的使用-
GCD的使用步驟
- 創(chuàng)建線程隊列:主隊列,全局并行隊列,手動創(chuàng)建串行隊列
- 選擇執(zhí)行方式:同步(較少使用),異步,延時
- 添加需要執(zhí)行的任務(wù):也就是想要創(chuàng)建隊列做什么,以Block塊語句形式創(chuàng)建
- 任務(wù)被執(zhí)行:Block按照設(shè)計被執(zhí)行
舉例
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"我在五秒后打印");
});
NSLog(@"線程被部署");
這段代碼的原型如下
void dispatch_after(dispatch_time_t when,
dispatch_queue_t queue,
dispatch_block_t block);
- 首先,創(chuàng)建線程隊列,本例中我們使用主隊列,所以直接使用dispatch_get_main_queue()
- 然后,選擇執(zhí)行方式,本例使用延時方法dispatch_after
- 添加需要執(zhí)行的任務(wù),我們打印了一下log
4.任務(wù)被執(zhí)行:

異步執(zhí)行線程
異步后臺線程
主要用途:執(zhí)行較慢的任務(wù),例如大量計算,網(wǎng)絡(luò)請求等
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"在異步并行隊列中執(zhí)行");
});
dispatch_queue_t queue = dispatch_queue_create("com.realank.GCDDemo.myQueue", NULL);
dispatch_async(queue, ^{
NSLog(@"在異步串行隊列中執(zhí)行");
});
上面的代碼,分別創(chuàng)建了一個異步后臺并行線程和一個自創(chuàng)建的異步后臺串行線程。
異步主線程
主要用途:用于在后臺線程的任務(wù)將要完成時,切換到主線程更新UI
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"在異步主線程中執(zhí)行");
});
同步執(zhí)行線程
同步后臺線程
主要用途:在新線程中執(zhí)行任務(wù),并且等待線程執(zhí)行完畢再向后執(zhí)行,幾乎不用
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"在同步并行隊列中執(zhí)行");
});
dispatch_queue_t queue = dispatch_queue_create("com.realank.GCDDemo.myQueue", NULL);
dispatch_sync(queue, ^{
NSLog(@"在同步串行隊列中執(zhí)行");
});
上面的代碼,分別創(chuàng)建了一個異步后臺并行線程和一個自創(chuàng)建的異步后臺串行線程。
同步主線程(慎用)
主要用途:只有在其它線程中才可能執(zhí)行此方法,否則會死鎖
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@“在同步主線程中執(zhí)行,慎用,否則會死鎖”);
});
延時執(zhí)行線程
主要用途:用于等待一段時間以后再執(zhí)行的任務(wù)
dispatch_queue_t queue = dispatch_get_main_queue();
// 也可以使用其它線程
// dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// dispatch_queue_t queue = dispatch_queue_create("com.realank.GCDDemo.myQueue2", NULL);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), queue, ^{
NSLog(@"延時2秒執(zhí)行");
});
NSLog(@"延時線程已部署");
-GCD的總結(jié)-
創(chuàng)建線程隊列
主隊列:
dispatch_queue_t queue = dispatch_get_main_queue();
全局并行隊列:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
手動創(chuàng)建串行隊列:
dispatch_queue_t queue = dispatch_queue_create("com.realank.GCDDemo.myQueue", NULL);
線程執(zhí)行方式
異步:
void dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
同步(慎用):
void dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
延時:
void dispatch_after(dispatch_time_t when,
dispatch_queue_t queue,
dispatch_block_t block);
關(guān)于循環(huán)強(qiáng)引用
在block中使用self,或者使用屬性(會隱含調(diào)用self),會讓block持有其類實例,如果此時block,又被存儲為類實例的copy或strong屬性,就會造成循環(huán)強(qiáng)引用。
在GCD的block使用中,不會造成類實例對block的引用,但是為了以防萬一,我習(xí)慣在Block中統(tǒng)一使用weakSelf來引用屬性或方法。
__weak __typeof(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
weakSelf.string = @“hello";
});