(GeekBand) iOS高級(jí)編程第三周--GCD

什么是GCD

全稱(chēng)是Grand Central Dispatch垫言,可譯為“偉大(牛逼)的中樞調(diào)度器”
純C語(yǔ)言呕屎,提供了非常多強(qiáng)大的函數(shù)

GCD的優(yōu)勢(shì)

GCD是蘋(píng)果公司為多核的并行運(yùn)算提出的解決方案
GCD會(huì)自動(dòng)利用更多的CPU內(nèi)核(比如雙核底靠、四核)
GCD會(huì)自動(dòng)管理線(xiàn)程的生命周期(創(chuàng)建線(xiàn)程友存、調(diào)度任務(wù)缤剧、銷(xiāo)毀線(xiàn)程)
程序員只需要告訴GCD想要執(zhí)行什么任務(wù)学辱,不需要編寫(xiě)任何線(xiàn)程管理代碼

GCD中有2個(gè)核心概念

任務(wù):執(zhí)行什么操作
隊(duì)列:用來(lái)存放任務(wù)

GCD的使用就2個(gè)步驟

定制任務(wù)
確定想做的事情

@@將任務(wù)添加到隊(duì)列中
GCD會(huì)自動(dòng)將隊(duì)列中的任務(wù)取出核畴,放到對(duì)應(yīng)的線(xiàn)程中執(zhí)行
任務(wù)的取出遵循隊(duì)列的FIFO原則:先進(jìn)先出膝但,后進(jìn)后出

GCD中有2個(gè)用來(lái)執(zhí)行任務(wù)的常用函數(shù)

用同步的方式執(zhí)行任務(wù)

dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
queue:隊(duì)列
block:任務(wù)

用異步的方式執(zhí)行任務(wù)

dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

同步和異步的區(qū)別

同步:只能在當(dāng)前線(xiàn)程中執(zhí)行任務(wù),不具備開(kāi)啟新線(xiàn)程的能力
異步:可以在新的線(xiàn)程中執(zhí)行任務(wù)膛檀,具備開(kāi)啟新線(xiàn)程的能力

GCD中還有個(gè)用來(lái)執(zhí)行任務(wù)的函數(shù):

dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);
在前面的任務(wù)執(zhí)行結(jié)束后它才執(zhí)行锰镀,而且它后面的任務(wù)等它執(zhí)行完成之后才會(huì)執(zhí)行

GCD的隊(duì)列可以分為2大類(lèi)型

并發(fā)隊(duì)列(Concurrent Dispatch Queue)

可以讓多個(gè)任務(wù)并發(fā)(同時(shí))執(zhí)行(自動(dòng)開(kāi)啟多個(gè)線(xiàn)程同時(shí)執(zhí)行任務(wù))
并發(fā)功能只有在異步(dispatch_async)函數(shù)下才有效

串行隊(duì)列(Serial Dispatch Queue)

讓任務(wù)一個(gè)接著一個(gè)地執(zhí)行(一個(gè)任務(wù)執(zhí)行完畢后娘侍,再執(zhí)行下一個(gè)任務(wù))

有4個(gè)術(shù)語(yǔ)比較容易混淆:同步、異步泳炉、并發(fā)憾筏、串行

同步和異步主要影響:能不能開(kāi)啟新的線(xiàn)程

同步:只是在當(dāng)前線(xiàn)程中執(zhí)行任務(wù),不具備開(kāi)啟新線(xiàn)程的能力
異步:可以在新的線(xiàn)程中執(zhí)行任務(wù)花鹅,具備開(kāi)啟新線(xiàn)程的能力

并發(fā)和串行主要影響:任務(wù)的執(zhí)行方式

并發(fā):多個(gè)任務(wù)并發(fā)(同時(shí))執(zhí)行
串行:一個(gè)任務(wù)執(zhí)行完畢后氧腰,再執(zhí)行下一個(gè)任務(wù)

并發(fā)隊(duì)列

使用dispatch_queue_create函數(shù)創(chuàng)建隊(duì)列
dispatch_queue_t
dispatch_queue_create(const char *label, // 隊(duì)列名稱(chēng) 
dispatch_queue_attr_t attr); // 隊(duì)列的類(lèi)型

創(chuàng)建并發(fā)隊(duì)列
dispatch_queue_t queue = dispatch_queue_create("GeekBand", DISPATCH_QUEUE_CONCURRENT);

GCD默認(rèn)已經(jīng)提供了全局的并發(fā)隊(duì)列,供整個(gè)應(yīng)用使用刨肃,可以無(wú)需手動(dòng)創(chuàng)建
使用dispatch_get_global_queue函數(shù)獲得全局的并發(fā)隊(duì)列
dispatch_queue_t dispatch_get_global_queue(
dispatch_queue_priority_t priority, // 隊(duì)列的優(yōu)先級(jí)
unsigned long flags); // 此參數(shù)暫時(shí)無(wú)用古拴,用0即可

獲得全局并發(fā)隊(duì)列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 

全局并發(fā)隊(duì)列的優(yōu)先級(jí)
#define DISPATCH_QUEUE_PRIORITY_HIGH 2 // 高
#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 // 默認(rèn)(中)
#define DISPATCH_QUEUE_PRIORITY_LOW (-2) // 低
#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN // 后臺(tái)

串行隊(duì)列

###使用dispatch_queue_create函數(shù)創(chuàng)建串行隊(duì)列
創(chuàng)建串行隊(duì)列(隊(duì)列類(lèi)型傳遞NULL或者DISPATCH_QUEUE_SERIAL)
dispatch_queue_t queue = dispatch_queue_create("GeekBand", NULL); 

###使用主隊(duì)列(跟主線(xiàn)程相關(guān)聯(lián)的隊(duì)列)
主隊(duì)列是GCD自帶的一種特殊的串行隊(duì)列
放在主隊(duì)列中的任務(wù),都會(huì)放到主線(xiàn)程中執(zhí)行
使用dispatch_get_main_queue()獲得主隊(duì)列
dispatch_queue_t queue = dispatch_get_main_queue();

注意:

凡是函數(shù)名種帶有create\copy\new\retain等字眼, 都應(yīng)該在不需要使用這個(gè)數(shù)據(jù)的時(shí)候進(jìn)行release真友。GCD的數(shù)據(jù)類(lèi)型在ARC環(huán)境下不需要再做release黄痪。CF(Core Foundation)的數(shù)據(jù)類(lèi)型在ARC環(huán)境下還是需要再做release。

各隊(duì)列的執(zhí)行效果

Paste_Image.png

線(xiàn)程之間的通信

從子線(xiàn)程回到主線(xiàn)程
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // 執(zhí)行耗時(shí)的異步操作...
      dispatch_async(dispatch_get_main_queue(), ^{
        // 回到主線(xiàn)程盔然,執(zhí)行UI刷新操作
        });
});

延時(shí)執(zhí)行

iOS常見(jiàn)的延時(shí)執(zhí)行

調(diào)用NSObject的方法

[self performSelector:@selector(run) withObject:nil afterDelay:2.0];
// 2秒后再調(diào)用self的run方法

使用GCD函數(shù)

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 2秒后異步執(zhí)行這里的代碼...
});

使用NSTimer(時(shí)間可能不準(zhǔn))

[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(test) userInfo:nil repeats:NO

一次性代碼

使用dispatch_once函數(shù)能保證某段代碼在程序運(yùn)行過(guò)程中只被執(zhí)行1次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 只執(zhí)行1次的代碼(這里面默認(rèn)是線(xiàn)程安全的)
});

定時(shí)器

// 創(chuàng)建Timer
self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
// 設(shè)置定時(shí)器的觸發(fā)時(shí)間(1秒后)和時(shí)間間隔(每隔2秒)
dispatch_source_set_timer(self.timer, dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), 2 * NSEC_PER_SEC, 0);
// 設(shè)置回調(diào)
dispatch_source_set_event_handler(self.timer, ^{
    NSLog(@"Timer %@", [NSThread currentThread]);
});
// 開(kāi)始定時(shí)器
dispatch_resume(self.timer);
取消定時(shí)器
dispatch_cancel(self.timer);
self.timer = nil;

快速迭代

使用dispatch_apply函數(shù)能進(jìn)行快速迭代遍歷
dispatch_apply(10, dispatch_get_global_queue(0, 0), ^(size_t index){
// 執(zhí)行10次代碼桅打,index順序不確定
});

隊(duì)列組

有這么1種需求
首先:分別異步執(zhí)行2個(gè)耗時(shí)的操作
其次:等2個(gè)異步操作都執(zhí)行完畢后,再回到主線(xiàn)程執(zhí)行操作

如果想要快速高效地實(shí)現(xiàn)上述需求愈案,可以考慮用隊(duì)列組

dispatch_group_t group =  dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // 執(zhí)行1個(gè)耗時(shí)的異步操作
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // 執(zhí)行1個(gè)耗時(shí)的異步操作
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    // 等前面的異步操作都執(zhí)行完畢后挺尾,回到主線(xiàn)程...
});

單例模式

單例模式的作用

可以保證在程序運(yùn)行過(guò)程,一個(gè)類(lèi)只有一個(gè)實(shí)例站绪,而且該實(shí)例易于供外界訪(fǎng)問(wèn)
從而方便地控制了實(shí)例個(gè)數(shù)遭铺,并節(jié)約系統(tǒng)資源

單例模式的使用場(chǎng)合

在整個(gè)應(yīng)用程序中,共享一份資源(這份資源只需要?jiǎng)?chuàng)建初始化1次)

ARC中恢准,單例模式的實(shí)現(xiàn)
在.m中保留一個(gè)全局的static的實(shí)例
static id _instance;

重寫(xiě)allocWithZone:方法魂挂,在這里創(chuàng)建唯一的實(shí)例(注意線(xiàn)程安全)
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [super allocWithZone:zone];
    });
    return _instance;
}

提供1個(gè)類(lèi)方法讓外界訪(fǎng)問(wèn)唯一的實(shí)例
+ (instancetype)sharedInstance
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[self alloc] init];
    });
    return _instance;
}

實(shí)現(xiàn)copyWithZone:方法
- (id)copyWithZone:(struct _NSZone *)zone
{
    return _instance;
}

滿(mǎn)地打滾賣(mài)萌求贊,如果本文幫助到你馁筐,輕點(diǎn)下方的紅心锰蓬,給作者君增加更新的動(dòng)力。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末眯漩,一起剝皮案震驚了整個(gè)濱河市芹扭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌赦抖,老刑警劉巖舱卡,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異队萤,居然都是意外死亡轮锥,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén)要尔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)舍杜,“玉大人新娜,你說(shuō)我怎么就攤上這事〖燃ǎ” “怎么了概龄?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)饲握。 經(jīng)常有香客問(wèn)我私杜,道長(zhǎng),這世上最難降的妖魔是什么救欧? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任衰粹,我火速辦了婚禮,結(jié)果婚禮上笆怠,老公的妹妹穿的比我還像新娘铝耻。我一直安慰自己,他們只是感情好蹬刷,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布田篇。 她就那樣靜靜地躺著,像睡著了一般箍铭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上椎镣,一...
    開(kāi)封第一講書(shū)人閱讀 49,749評(píng)論 1 289
  • 那天诈火,我揣著相機(jī)與錄音,去河邊找鬼状答。 笑死冷守,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的惊科。 我是一名探鬼主播拍摇,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼馆截!你這毒婦竟也來(lái)了充活?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蜡娶,失蹤者是張志新(化名)和其女友劉穎混卵,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體窖张,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡幕随,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了宿接。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赘淮。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡辕录,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出梢卸,到底是詐尸還是另有隱情走诞,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布低剔,位于F島的核電站速梗,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏襟齿。R本人自食惡果不足惜姻锁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望猜欺。 院中可真熱鬧位隶,春花似錦、人聲如沸开皿。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)赋荆。三九已至笋妥,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間窄潭,已是汗流浹背春宣。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留嫉你,地道東北人月帝。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像幽污,于是被迫代替她去往敵國(guó)和親嚷辅。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容