日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

c语言gcd 简易函数,简单[GCD]用法详细总结(上)

發(fā)布時(shí)間:2023/12/18 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c语言gcd 简易函数,简单[GCD]用法详细总结(上) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

原文鏈接:https://www.jianshu.com/p/2d57c72016c6

本文用來(lái)介紹 iOS 多線程中 GCD 的相關(guān)知識(shí)以及使用方法。通過(guò)本文,您將了解到:

1. GCD 簡(jiǎn)介

2. GCD 任務(wù)和隊(duì)列

3. GCD 的使用步驟

4. GCD 的基本使用(6種不同組合區(qū)別)

1. GCD 簡(jiǎn)介

什么是 GCD 呢?我們先來(lái)看看百度百科的解釋簡(jiǎn)單了解下概念Grand Central Dispatch(GCD)是 Apple 開(kāi)發(fā)的一個(gè)多核編程的較新的解決方法。它主要用于優(yōu)化應(yīng)用程序以支持多核處理器以及其他對(duì)稱多處理系統(tǒng)。它是一個(gè)在線程池模式的基礎(chǔ)上執(zhí)行的并發(fā)任務(wù)。在 Mac OS X 10.6 雪豹中首次推出,也可在 iOS 4 及以上版本使用。

為什么要用 GCD 呢?

因?yàn)?GCD 有很多好處啊,具體如下:GCD 可用于多核的并行運(yùn)算

GCD 會(huì)自動(dòng)利用更多的 CPU 內(nèi)核(比如雙核、四核)

GCD 會(huì)自動(dòng)管理線程的生命周期(創(chuàng)建線程、調(diào)度任務(wù)、銷毀線程)

程序員只需要告訴 GCD 想要執(zhí)行什么任務(wù),不需要編寫任何線程管理代碼

既然 GCD 有這么多的好處,那么下面我們就來(lái)系統(tǒng)的學(xué)習(xí)一下 GCD 的使用方法。

2. GCD 任務(wù)和隊(duì)列

學(xué)習(xí) GCD 之前,先來(lái)了解 GCD 中兩個(gè)核心概念:任務(wù)和隊(duì)列。

任務(wù):就是執(zhí)行操作的意思,換句話說(shuō)就是你在線程中執(zhí)行的那段代碼。在 GCD 中是放在 block 中的。執(zhí)行任務(wù)有兩種方式:同步執(zhí)行(sync)和異步執(zhí)行(async)。兩者的主要區(qū)別是:是否等待隊(duì)列的任務(wù)執(zhí)行結(jié)束,以及是否具備開(kāi)啟新線程的能力。

同步執(zhí)行(sync):

同步添加任務(wù)到指定的隊(duì)列中,在添加的任務(wù)執(zhí)行結(jié)束之前,會(huì)一直等待,直到隊(duì)列里面的任務(wù)完成之后再繼續(xù)執(zhí)行。

只能在當(dāng)前線程中執(zhí)行任務(wù),不具備開(kāi)啟新線程的能力。

異步執(zhí)行(async):

異步添加任務(wù)到指定的隊(duì)列中,它不會(huì)做任何等待,可以繼續(xù)執(zhí)行任務(wù)。

可以在新的線程中執(zhí)行任務(wù),具備開(kāi)啟新線程的能力。

舉個(gè)簡(jiǎn)單例子:你要打電話給小明和小白。

同步執(zhí)行就是,你打電話給小明的時(shí)候,不能同時(shí)打給小白,等到給小明打完了,才能打給小白(等待任務(wù)執(zhí)行結(jié)束)。而且只能用當(dāng)前的電話(不具備開(kāi)啟新線程的能力)。

而異步執(zhí)行就是,你打電話給小明的時(shí)候,不等和小明通話結(jié)束,還能直接給小白打電話,不用等著和小明通話結(jié)束再打(不用等待任務(wù)執(zhí)行結(jié)束)。除了當(dāng)前電話,你還可以使用其他所能使用的電話(具備開(kāi)啟新線程的能力)。

注意:異步執(zhí)行(async)雖然具有開(kāi)啟新線程的能力,但是并不一定開(kāi)啟新線程。這跟任務(wù)所指定的隊(duì)列類型有關(guān)(下面會(huì)講)。

隊(duì)列(Dispatch Queue):這里的隊(duì)列指執(zhí)行任務(wù)的等待隊(duì)列,即用來(lái)存放任務(wù)的隊(duì)列。隊(duì)列是一種特殊的線性表,采用 FIFO(先進(jìn)先出)的原則,即新任務(wù)總是被插入到隊(duì)列的末尾,而讀取任務(wù)的時(shí)候總是從隊(duì)列的頭部開(kāi)始讀取。每讀取一個(gè)任務(wù),則從隊(duì)列中釋放一個(gè)任務(wù)。隊(duì)列的結(jié)構(gòu)可參考下圖:

Serial串行隊(duì)列.png

在 GCD 中有兩種隊(duì)列:串行隊(duì)列和并發(fā)隊(duì)列。兩者都符合 FIFO(先進(jìn)先出)的原則。兩者的主要區(qū)別是:執(zhí)行順序不同,以及開(kāi)啟線程數(shù)不同。

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

每次只有一個(gè)任務(wù)被執(zhí)行。讓任務(wù)一個(gè)接著一個(gè)地執(zhí)行。(只開(kāi)啟一個(gè)線程,一個(gè)任務(wù)執(zhí)行完畢后,再執(zhí)行下一個(gè)任務(wù))

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

可以讓多個(gè)任務(wù)并發(fā)(同時(shí))執(zhí)行。(可以開(kāi)啟多個(gè)線程,并且同時(shí)執(zhí)行任務(wù))注意:并發(fā)隊(duì)列的并發(fā)功能只有在異步(dispatch_async)函數(shù)下才有效

兩者具體區(qū)別如下兩圖所示。

串行隊(duì)列.png

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

3. GCD 的使用步驟

GCD 的使用步驟其實(shí)很簡(jiǎn)單,只有兩步。

1.創(chuàng)建一個(gè)隊(duì)列(串行隊(duì)列或并發(fā)隊(duì)列)

2.將任務(wù)追加到任務(wù)的等待隊(duì)列中,然后系統(tǒng)就會(huì)根據(jù)任務(wù)類型執(zhí)行任務(wù)(同步執(zhí)行或異步執(zhí)行)

下邊來(lái)看看隊(duì)列的創(chuàng)建方法/獲取方法,以及任務(wù)的創(chuàng)建方法。

3.1 隊(duì)列的創(chuàng)建方法/獲取方法

可以使用dispatch_queue_create來(lái)創(chuàng)建隊(duì)列,需要傳入兩個(gè)參數(shù),第一個(gè)參數(shù)表示隊(duì)列的唯一標(biāo)識(shí)符,用于 DEBUG,可為空,Dispatch Queue 的名稱推薦使用應(yīng)用程序 ID 這種逆序全程域名;第二個(gè)參數(shù)用來(lái)識(shí)別是串行隊(duì)列還是并發(fā)隊(duì)列。DISPATCH_QUEUE_SERIAL表示串行隊(duì)列,DISPATCH_QUEUE_CONCURRENT表示并發(fā)隊(duì)列。// 串行隊(duì)列的創(chuàng)建方法dispatch_queue_tqueue= dispatch_queue_create("net.bujige.testQueue", DISPATCH_QUEUE_SERIAL);

// 并發(fā)隊(duì)列的創(chuàng)建方法dispatch_queue_tqueue= dispatch_queue_create("net.bujige.testQueue", DISPATCH_QUEUE_CONCURRENT);

對(duì)于串行隊(duì)列,GCD 提供了的一種特殊的串行隊(duì)列:主隊(duì)列(Main Dispatch Queue)。

a.所有放在主隊(duì)列中的任務(wù),都會(huì)放到主線程中執(zhí)行。

b.可使用dispatch_get_main_queue()獲得主隊(duì)列。// 主隊(duì)列的獲取方法

dispatch_queue_t queue= dispatch_get_main_queue();

對(duì)于并發(fā)隊(duì)列,GCD 默認(rèn)提供了全局并發(fā)隊(duì)列(Global Dispatch Queue)。

a.可以使用dispatch_get_global_queue來(lái)獲取。需要傳入兩個(gè)參數(shù)。第一個(gè)參數(shù)表示隊(duì)列優(yōu)先級(jí),一般用DISPATCH_QUEUE_PRIORITY_DEFAULT。第二個(gè)參數(shù)暫時(shí)沒(méi)用,用0即可。// 全局并發(fā)隊(duì)列的獲取方法

dispatch_queue_tqueue= dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

3.2 任務(wù)的創(chuàng)建方法

GCD 提供了同步執(zhí)行任務(wù)的創(chuàng)建方法dispatch_sync和異步執(zhí)行任務(wù)創(chuàng)建方法dispatch_async。// 同步執(zhí)行任務(wù)創(chuàng)建方法

dispatch_sync(queue, ^{// 這里放同步執(zhí)行任務(wù)代碼});

// 異步執(zhí)行任務(wù)創(chuàng)建方法

dispatch_async(queue, ^{// 這里放異步執(zhí)行任務(wù)代碼});

雖然使用 GCD 只需兩步,但是既然我們有兩種隊(duì)列(串行隊(duì)列/并發(fā)隊(duì)列),兩種任務(wù)執(zhí)行方式(同步執(zhí)行/異步執(zhí)行),那么我們就有了四種不同的組合方式。這四種不同的組合方式是:同步執(zhí)行 + 并發(fā)隊(duì)列

異步執(zhí)行 + 并發(fā)隊(duì)列

同步執(zhí)行 + 串行隊(duì)列

異步執(zhí)行 + 串行隊(duì)列

實(shí)際上,剛才還說(shuō)了兩種特殊隊(duì)列:全局并發(fā)隊(duì)列、主隊(duì)列。全局并發(fā)隊(duì)列可以作為普通并發(fā)隊(duì)列來(lái)使用。但是主隊(duì)列因?yàn)橛悬c(diǎn)特殊,所以我們就又多了兩種組合方式。這樣就有六種不同的組合方式了。同步執(zhí)行 + 主隊(duì)列

異步執(zhí)行 + 主隊(duì)列

那么這幾種不同組合方式各有什么區(qū)別呢,這里為了方便,先上結(jié)果,再來(lái)講解。你可以直接查看表格結(jié)果,然后跳過(guò)4. GCD的基本使用。

下邊我們來(lái)分別講講這幾種不同的組合方式的使用方法。

4. GCD 的基本使用

先來(lái)講講并發(fā)隊(duì)列的兩種執(zhí)行方式。

4.1 同步執(zhí)行 + 并發(fā)隊(duì)列

在當(dāng)前線程中執(zhí)行任務(wù),不會(huì)開(kāi)啟新線程,執(zhí)行完一個(gè)任務(wù),再執(zhí)行下一個(gè)任務(wù)。/**

* 同步執(zhí)行 + 并發(fā)隊(duì)列

* 特點(diǎn):在當(dāng)前線程中執(zhí)行任務(wù),不會(huì)開(kāi)啟新線程,執(zhí)行完一個(gè)任務(wù),再執(zhí)行下一個(gè)任務(wù)。

*/

- (void)syncConcurrent {

NSLog(@"currentThread---%@",[NSThreadcurrentThread]);

// 打印當(dāng)前線程N(yùn)SLog(@"syncConcurrent---begin");

dispatch_queue_tqueue = dispatch_queue_create("net.bujige.testQueue", DISPATCH_QUEUE_CONCURRENT);

dispatch_sync(queue, ^{

// 追加任務(wù)1

for(inti =0; i <2; ++i) {

[NSThreadsleepForTimeInterval:2];// 模擬耗時(shí)操作

NSLog(@"1---%@",[NSThreadcurrentThread]);// 打印當(dāng)前線程

}

});

dispatch_sync(queue, ^{

// 追加任務(wù)2

for(inti =0; i <2; ++i) {

[NSThreadsleepForTimeInterval:2];// 模擬耗時(shí)操作

NSLog(@"2---%@",[NSThreadcurrentThread]);// 打印當(dāng)前線程

}

});

dispatch_sync(queue, ^{

// 追加任務(wù)3

for(inti =0; i <2; ++i) {

[NSThreadsleepForTimeInterval:2];// 模擬耗時(shí)操作

NSLog(@"3---%@",[NSThreadcurrentThread]);// 打印當(dāng)前線程

}

});

NSLog(@"syncConcurrent---end");}輸出結(jié)果:

2018-02-23 20:34:55.095932+0800 YSC-GCD-demo[19892:4996930] currentThread---{number = 1, name = main}

2018-02-23 20:34:55.096086+0800 YSC-GCD-demo[19892:4996930] syncConcurrent---begin

2018-02-23 20:34:57.097589+0800 YSC-GCD-demo[19892:4996930] 1---{number = 1, name = main}

2018-02-23 20:34:59.099100+0800 YSC-GCD-demo[19892:4996930] 1---{number = 1, name = main}

2018-02-23 20:35:01.099843+0800 YSC-GCD-demo[19892:4996930] 2---{number = 1, name = main}

2018-02-23 20:35:03.101171+0800 YSC-GCD-demo[19892:4996930] 2---{number = 1, name = main}

2018-02-23 20:35:05.101750+0800 YSC-GCD-demo[19892:4996930] 3---{number = 1, name = main}

2018-02-23 20:35:07.102414+0800 YSC-GCD-demo[19892:4996930] 3---{number = 1, name = main}

2018-02-23 20:35:07.102575+0800 YSC-GCD-demo[19892:4996930] syncConcurrent---end

從同步執(zhí)行 + 并發(fā)隊(duì)列中可看到:

a.所有任務(wù)都是在當(dāng)前線程(主線程)中執(zhí)行的,沒(méi)有開(kāi)啟新的線程(同步執(zhí)行不具備開(kāi)啟新線程的能力)。

b.所有任務(wù)都在打印的syncConcurrent---begin和syncConcurrent---end之間執(zhí)行的(同步任務(wù)需要等待隊(duì)列的任務(wù)執(zhí)行結(jié)束)。

任務(wù)按順序執(zhí)行的。按順序執(zhí)行的原因:雖然并發(fā)隊(duì)列可以開(kāi)啟多個(gè)線程,并且同時(shí)執(zhí)行多個(gè)任務(wù)。但是因?yàn)楸旧聿荒軇?chuàng)建新線程,只有當(dāng)前線程這一個(gè)線程(同步任務(wù)不具備開(kāi)啟新線程的能力),所以也就不存在并發(fā)。而且當(dāng)前線程只有等待當(dāng)前隊(duì)列中正在執(zhí)行的任務(wù)執(zhí)行完畢之后,才能繼續(xù)接著執(zhí)行下面的操作(同步任務(wù)需要等待隊(duì)列的任務(wù)執(zhí)行結(jié)束)。所以任務(wù)只能一個(gè)接一個(gè)按順序執(zhí)行,不能同時(shí)被執(zhí)行。

4.2 異步執(zhí)行 + 并發(fā)隊(duì)列

可以開(kāi)啟多個(gè)線程,任務(wù)交替(同時(shí))執(zhí)行。/**

* 異步執(zhí)行 + 并發(fā)隊(duì)列

* 特點(diǎn):可以開(kāi)啟多個(gè)線程,任務(wù)交替(同時(shí))執(zhí)行。

*/- (void)asyncConcurrent {

NSLog(@"currentThread---%@",[NSThreadcurrentThread]);

// 打印當(dāng)前線程N(yùn)SLog(@"asyncConcurrent---begin");

dispatch_queue_tqueue = dispatch_queue_create("net.bujige.testQueue", DISPATCH_QUEUE_CONCURRENT);

dispatch_async(queue, ^{

// 追加任務(wù)1for(inti =0; i <2; ++i) {

[NSThreadsleepForTimeInterval:2];// 模擬耗時(shí)操作

NSLog(@"1---%@",[NSThreadcurrentThread]);// 打印當(dāng)前線程}

});

dispatch_async(queue, ^{

// 追加任務(wù)2

for(inti =0; i <2; ++i) {

[NSThreadsleepForTimeInterval:2];// 模擬耗時(shí)操作

NSLog(@"2---%@",[NSThreadcurrentThread]);// 打印當(dāng)前線程

}

});

dispatch_async(queue, ^{

// 追加任務(wù)3

for(inti =0; i <2; ++i) {

[NSThreadsleepForTimeInterval:2];// 模擬耗時(shí)操作

NSLog(@"3---%@",[NSThreadcurrentThread]);// 打印當(dāng)前線程

}

});

NSLog(@"asyncConcurrent---end");}輸出結(jié)果:

2018-02-23 20:36:41.769269+0800 YSC-GCD-demo[19929:5005237] currentThread---{number = 1, name = main}

2018-02-23 20:36:41.769496+0800 YSC-GCD-demo[19929:5005237] asyncConcurrent---begin

2018-02-23 20:36:41.769725+0800 YSC-GCD-demo[19929:5005237] asyncConcurrent---end

2018-02-23 20:36:43.774442+0800 YSC-GCD-demo[19929:5005566] 2---{number = 5, name = (null)}

2018-02-23 20:36:43.774440+0800 YSC-GCD-demo[19929:5005567] 3---{number = 4, name = (null)}

2018-02-23 20:36:43.774440+0800 YSC-GCD-demo[19929:5005565] 1---{number = 3, name = (null)}

2018-02-23 20:36:45.779286+0800 YSC-GCD-demo[19929:5005567] 3---{number = 4, name = (null)}

2018-02-23 20:36:45.779302+0800 YSC-GCD-demo[19929:5005565] 1---{number = 3, name = (null)}

2018-02-23 20:36:45.779286+0800 YSC-GCD-demo[19929:5005566] 2---{number = 5, name = (null)}

在異步執(zhí)行 + 并發(fā)隊(duì)列中可以看出:

a.除了當(dāng)前線程(主線程),系統(tǒng)又開(kāi)啟了3個(gè)線程,并且任務(wù)是交替/同時(shí)執(zhí)行的。(異步執(zhí)行具備開(kāi)啟新線程的能力。且并發(fā)隊(duì)列可開(kāi)啟多個(gè)線程,同時(shí)執(zhí)行多個(gè)任務(wù))。

b.所有任務(wù)是在打印的syncConcurrent---begin和syncConcurrent---end之后才執(zhí)行的。說(shuō)明當(dāng)前線程沒(méi)有等待,而是直接開(kāi)啟了新線程,在新線程中執(zhí)行任務(wù)(異步執(zhí)行不做等待,可以繼續(xù)執(zhí)行任務(wù))。

接下來(lái)再來(lái)講講串行隊(duì)列的兩種執(zhí)行方式。

4.3 同步執(zhí)行 + 串行隊(duì)列

不會(huì)開(kāi)啟新線程,在當(dāng)前線程執(zhí)行任務(wù)。任務(wù)是串行的,執(zhí)行完一個(gè)任務(wù),再執(zhí)行下一個(gè)任務(wù)。/**

* 同步執(zhí)行 + 串行隊(duì)列

* 特點(diǎn):不會(huì)開(kāi)啟新線程,在當(dāng)前線程執(zhí)行任務(wù)。任務(wù)是串行的,執(zhí)行完一個(gè)任務(wù),再執(zhí)行下一個(gè)任務(wù)。

*/

- (void)syncSerial {

NSLog(@"currentThread---%@",[NSThreadcurrentThread]);// 打印當(dāng)前線程

NSLog(@"syncSerial---begin");

dispatch_queue_tqueue = dispatch_queue_create("net.bujige.testQueue", DISPATCH_QUEUE_SERIAL);

dispatch_sync(queue, ^{

// 追加任務(wù)1

for(inti =0; i <2; ++i) {

[NSThreadsleepForTimeInterval:2];// 模擬耗時(shí)操作

NSLog(@"1---%@",[NSThreadcurrentThread]);// 打印當(dāng)前線程

}

});

dispatch_sync(queue, ^{

// 追加任務(wù)2

for(inti =0; i <2; ++i) {

[NSThreadsleepForTimeInterval:2];// 模擬耗時(shí)操作

NSLog(@"2---%@",[NSThreadcurrentThread]);// 打印當(dāng)前線程

}

});

dispatch_sync(queue, ^{

// 追加任務(wù)3

for(inti =0; i <2; ++i) {

[NSThreadsleepForTimeInterval:2];// 模擬耗時(shí)操作

NSLog(@"3---%@",[NSThreadcurrentThread]);// 打印當(dāng)前線程

}

});

NSLog(@"syncSerial---end");}輸出結(jié)果為:

2018-02-23 20:39:37.876811+0800 YSC-GCD-demo[19975:5017162] currentThread---{number = 1, name = main}

2018-02-23 20:39:37.876998+0800 YSC-GCD-demo[19975:5017162] syncSerial---begin

2018-02-23 20:39:39.878316+0800 YSC-GCD-demo[19975:5017162] 1---{number = 1, name = main}

2018-02-23 20:39:41.879829+0800 YSC-GCD-demo[19975:5017162] 1---{number = 1, name = main}

2018-02-23 20:39:43.880660+0800 YSC-GCD-demo[19975:5017162] 2---{number = 1, name = main}

2018-02-23 20:39:45.881265+0800 YSC-GCD-demo[19975:5017162] 2---{number = 1, name = main}

2018-02-23 20:39:47.882257+0800 YSC-GCD-demo[19975:5017162] 3---{number = 1, name = main}

2018-02-23 20:39:49.883008+0800 YSC-GCD-demo[19975:5017162] 3---{number = 1, name = main}

2018-02-23 20:39:49.883253+0800 YSC-GCD-demo[19975:5017162] syncSerial---end

在同步執(zhí)行 + 串行隊(duì)列可以看到:

a.所有任務(wù)都是在當(dāng)前線程(主線程)中執(zhí)行的,并沒(méi)有開(kāi)啟新的線程(同步執(zhí)行不具備開(kāi)啟新線程的能力)。

b.所有任務(wù)都在打印的syncConcurrent---begin和syncConcurrent---end之間執(zhí)行(同步任務(wù)需要等待隊(duì)列的任務(wù)執(zhí)行結(jié)束)。

c.任務(wù)是按順序執(zhí)行的(串行隊(duì)列每次只有一個(gè)任務(wù)被執(zhí)行,任務(wù)一個(gè)接一個(gè)按順序執(zhí)行)。

4.4 異步執(zhí)行 + 串行隊(duì)列

會(huì)開(kāi)啟新線程,但是因?yàn)槿蝿?wù)是串行的,執(zhí)行完一個(gè)任務(wù),再執(zhí)行下一個(gè)任務(wù)/**

* 異步執(zhí)行 + 串行隊(duì)列

* 特點(diǎn):會(huì)開(kāi)啟新線程,但是因?yàn)槿蝿?wù)是串行的,執(zhí)行完一個(gè)任務(wù),再執(zhí)行下一個(gè)任務(wù)。

*/

- (void)asyncSerial {

NSLog(@"currentThread---%@",[NSThreadcurrentThread]);// 打印當(dāng)前線程

NSLog(@"asyncSerial---begin");

dispatch_queue_tqueue = dispatch_queue_create("net.bujige.testQueue", DISPATCH_QUEUE_SERIAL);

dispatch_async(queue, ^{

// 追加任務(wù)1

for(inti =0; i <2; ++i) {

[NSThreadsleepForTimeInterval:2];// 模擬耗時(shí)操作

NSLog(@"1---%@",[NSThreadcurrentThread]);// 打印當(dāng)前線程

}

});

dispatch_async(queue, ^{

// 追加任務(wù)2

for(int i =0; i <2; ++i) {

[NSThreadsleepForTimeInterval:2];// 模擬耗時(shí)操作

NSLog(@"2---%@",[NSThreadcurrentThread]);// 打印當(dāng)前線程

}

});

dispatch_async(queue, ^{

// 追加任務(wù)3

for(int i =0; i <2; ++i) {

[NSThreadsleepForTimeInterval:2];// 模擬耗時(shí)操作

NSLog(@"3---%@",[NSThreadcurrentThread]);// 打印當(dāng)前線程

}

});

NSLog(@"asyncSerial---end");}輸出結(jié)果為:

2018-02-23 20:41:17.029999+0800 YSC-GCD-demo[20008:5024757] currentThread---{number = 1, name = main}

2018-02-23 20:41:17.030212+0800 YSC-GCD-demo[20008:5024757] asyncSerial---begin

2018-02-23 20:41:17.030364+0800 YSC-GCD-demo[20008:5024757] asyncSerial---end

2018-02-23 20:41:19.035379+0800 YSC-GCD-demo[20008:5024950] 1---{number = 3, name = (null)}

2018-02-23 20:41:21.037140+0800 YSC-GCD-demo[20008:5024950] 1---{number = 3, name = (null)}

2018-02-23 20:41:23.042220+0800 YSC-GCD-demo[20008:5024950] 2---{number = 3, name = (null)}

2018-02-23 20:41:25.042971+0800 YSC-GCD-demo[20008:5024950] 2---{number = 3, name = (null)}

2018-02-23 20:41:27.047690+0800 YSC-GCD-demo[20008:5024950] 3---{number = 3, name = (null)}

2018-02-23 20:41:29.052327+0800 YSC-GCD-demo[20008:5024950] 3---{number = 3, name = (null)}

在異步執(zhí)行 + 串行隊(duì)列可以看到:

a.開(kāi)啟了一條新線程(異步執(zhí)行具備開(kāi)啟新線程的能力,串行隊(duì)列只開(kāi)啟一個(gè)線程)。

b.所有任務(wù)是在打印的syncConcurrent---begin和syncConcurrent---end之后才開(kāi)始執(zhí)行的(異步執(zhí)行不會(huì)做任何等待,可以繼續(xù)執(zhí)行任務(wù))。

c.任務(wù)是按順序執(zhí)行的(串行隊(duì)列每次只有一個(gè)任務(wù)被執(zhí)行,任務(wù)一個(gè)接一個(gè)按順序執(zhí)行)。

下邊講講剛才我們提到過(guò)的特殊隊(duì)列:主隊(duì)列。

主隊(duì)列:GCD自帶的一種特殊的串行隊(duì)列

所有放在主隊(duì)列中的任務(wù),都會(huì)放到主線程中執(zhí)行

可使用dispatch_get_main_queue()獲得主隊(duì)列

我們?cè)賮?lái)看看主隊(duì)列的兩種組合方式。

4.5 同步執(zhí)行 + 主隊(duì)列

同步執(zhí)行 + 主隊(duì)列在不同線程中調(diào)用結(jié)果也是不一樣,在主線程中調(diào)用會(huì)出現(xiàn)死鎖,而在其他線程中則不會(huì)。

4.5.1 在主線程中調(diào)用同步執(zhí)行 + 主隊(duì)列

互相等待卡住不可行/**

* 同步執(zhí)行 + 主隊(duì)列

* 特點(diǎn)(主線程調(diào)用):互等卡主不執(zhí)行。

* 特點(diǎn)(其他線程調(diào)用):不會(huì)開(kāi)啟新線程,執(zhí)行完一個(gè)任務(wù),再執(zhí)行下一個(gè)任務(wù)。

*/

- (void)syncMain {

NSLog(@"currentThread---%@",[NSThreadcurrentThread]);

// 打印當(dāng)前線程

NSLog(@"syncMain---begin");

dispatch_queue_tqueue = dispatch_get_main_queue();

dispatch_sync(queue, ^{

// 追加任務(wù)1

for(inti =0; i <2; ++i) {

[NSThreadsleepForTimeInterval:2];// 模擬耗時(shí)操作

NSLog(@"1---%@",[NSThreadcurrentThread]);// 打印當(dāng)前線程

}

});

dispatch_sync(queue, ^{

// 追加任務(wù)2

for(inti =0; i <2; ++i) {

[NSThreadsleepForTimeInterval:2];// 模擬耗時(shí)操作

NSLog(@"2---%@",[NSThreadcurrentThread]);// 打印當(dāng)前線程

}

});

dispatch_sync(queue, ^{

// 追加任務(wù)3

for(inti =0; i <2; ++i) {

[NSThreadsleepForTimeInterval:2];// 模擬耗時(shí)操作

NSLog(@"3---%@",[NSThreadcurrentThread]);// 打印當(dāng)前線程

}

});

NSLog(@"syncMain---end");}輸出結(jié)果

2018-02-23 20:42:36.842892+0800 YSC-GCD-demo[20041:5030982] currentThread---{number = 1, name = main}

2018-02-23 20:42:36.843050+0800 YSC-GCD-demo[20041:5030982] syncMain---begin

(lldb)

在同步執(zhí)行 + 主隊(duì)列可以驚奇的發(fā)現(xiàn):

在主線程中使用同步執(zhí)行 + 主隊(duì)列,追加到主線程的任務(wù)1、任務(wù)2、任務(wù)3都不再執(zhí)行了,而且syncMain---end也沒(méi)有打印,在XCode 9上還會(huì)報(bào)崩潰。這是為什么呢?

這是因?yàn)槲覀冊(cè)谥骶€程中執(zhí)行syncMain方法,相當(dāng)于把syncMain任務(wù)放到了主線程的隊(duì)列中。而同步執(zhí)行會(huì)等待當(dāng)前隊(duì)列中的任務(wù)執(zhí)行完畢,才會(huì)接著執(zhí)行。那么當(dāng)我們把任務(wù)1追加到主隊(duì)列中,任務(wù)1就在等待主線程處理完syncMain任務(wù)。而syncMain任務(wù)需要等待任務(wù)1執(zhí)行完畢,才能接著執(zhí)行。

那么,現(xiàn)在的情況就是syncMain任務(wù)和任務(wù)1都在等對(duì)方執(zhí)行完畢。這樣大家互相等待,所以就卡住了,所以我們的任務(wù)執(zhí)行不了,而且syncMain---end也沒(méi)有打印。

要是如果不在主線程中調(diào)用,而在其他線程中調(diào)用會(huì)如何呢?

4.5.2 在其他線程中調(diào)用同步執(zhí)行 + 主隊(duì)列

不會(huì)開(kāi)啟新線程,執(zhí)行完一個(gè)任務(wù),再執(zhí)行下一個(gè)任務(wù)// 使用 NSThread 的 detachNewThreadSelector 方法會(huì)創(chuàng)建線程,并自動(dòng)啟動(dòng)線程執(zhí)行selector 任務(wù)[NSThread detachNewThreadSelector:@selector(syncMain) toTarget:selfwithObject:nil];輸出結(jié)果:

2018-02-23 20:44:19.377321+0800 YSC-GCD-demo[20083:5040347] currentThread---{number = 3, name = (null)}

2018-02-23 20:44:19.377494+0800 YSC-GCD-demo[20083:5040347] syncMain---begin

2018-02-23 20:44:21.384716+0800 YSC-GCD-demo[20083:5040132] 1---{number = 1, name = main}

2018-02-23 20:44:23.386091+0800 YSC-GCD-demo[20083:5040132] 1---{number = 1, name = main}

2018-02-23 20:44:25.387687+0800 YSC-GCD-demo[20083:5040132] 2---{number = 1, name = main}

2018-02-23 20:44:27.388648+0800 YSC-GCD-demo[20083:5040132] 2---{number = 1, name = main}

2018-02-23 20:44:29.390459+0800 YSC-GCD-demo[20083:5040132] 3---{number = 1, name = main}

2018-02-23 20:44:31.391965+0800 YSC-GCD-demo[20083:5040132] 3---{number = 1, name = main}

2018-02-23 20:44:31.392513+0800 YSC-GCD-demo[20083:5040347] syncMain---end

在其他線程中使用同步執(zhí)行 + 主隊(duì)列可看到:

a.所有任務(wù)都是在主線程(非當(dāng)前線程)中執(zhí)行的,沒(méi)有開(kāi)啟新的線程(所有放在主隊(duì)列中的任務(wù),都會(huì)放到主線程中執(zhí)行)。

b.所有任務(wù)都在打印的syncConcurrent---begin和syncConcurrent---end之間執(zhí)行(同步任務(wù)需要等待隊(duì)列的任務(wù)執(zhí)行結(jié)束)。

c.任務(wù)是按順序執(zhí)行的(主隊(duì)列是串行隊(duì)列,每次只有一個(gè)任務(wù)被執(zhí)行,任務(wù)一個(gè)接一個(gè)按順序執(zhí)行)。

為什么現(xiàn)在就不會(huì)卡住了呢?

因?yàn)閟yncMain 任務(wù)放到了其他線程里,而任務(wù)1、任務(wù)2、任務(wù)3都在追加到主隊(duì)列中,這三個(gè)任務(wù)都會(huì)在主線程中執(zhí)行。syncMain任務(wù)在其他線程中執(zhí)行到追加任務(wù)1到主隊(duì)列中,因?yàn)橹麝?duì)列現(xiàn)在沒(méi)有正在執(zhí)行的任務(wù),所以,會(huì)直接執(zhí)行主隊(duì)列的任務(wù)1,等任務(wù)1執(zhí)行完畢,再接著執(zhí)行任務(wù)2、任務(wù)3。所以這里不會(huì)卡住線程。

4.6 異步執(zhí)行 + 主隊(duì)列

只在主線程中執(zhí)行任務(wù),執(zhí)行完一個(gè)任務(wù),再執(zhí)行下一個(gè)任務(wù)。/**

* 異步執(zhí)行 + 主隊(duì)列

* 特點(diǎn):只在主線程中執(zhí)行任務(wù),執(zhí)行完一個(gè)任務(wù),再執(zhí)行下一個(gè)任務(wù)

*/

- (void)asyncMain {

NSLog(@"currentThread---%@",[NSThreadcurrentThread]);// 打印當(dāng)前線程

NSLog(@"asyncMain---begin");

dispatch_queue_t queue = dispatch_get_main_queue();

dispatch_async(queue, ^{

// 追加任務(wù)1

for(int i =0; i <2; ++i) {

[NSThread sleepForTimeInterval:2];// 模擬耗時(shí)操作

NSLog(@"1---%@",[NSThread currentThread]);// 打印當(dāng)前線程

}

});

dispatch_async(queue, ^{

// 追加任務(wù)2

for(int i =0; i <2; ++i) {

[NSThread sleepForTimeInterval:2];// 模擬耗時(shí)操作

NSLog(@"2---%@",[NSThread currentThread]);// 打印當(dāng)前線程

}

});

dispatch_async(queue, ^{

// 追加任務(wù)3

for(int i =0; i <2; ++i) {

[NSThread sleepForTimeInterval:2];// 模擬耗時(shí)操作

NSLog(@"3---%@",[NSThread currentThread]);// 打印當(dāng)前線程

}

});

NSLog(@"asyncMain---end");}輸出結(jié)果:

2018-02-23 20:45:49.981505+0800 YSC-GCD-demo[20111:5046708] currentThread---{number = 1, name = main}

2018-02-23 20:45:49.981935+0800 YSC-GCD-demo[20111:5046708] asyncMain---begin

2018-02-23 20:45:49.982352+0800 YSC-GCD-demo[20111:5046708] asyncMain---end

2018-02-23 20:45:51.991096+0800 YSC-GCD-demo[20111:5046708] 1---{number = 1, name = main}

2018-02-23 20:45:53.991959+0800 YSC-GCD-demo[20111:5046708] 1---{number = 1, name = main}

2018-02-23 20:45:55.992937+0800 YSC-GCD-demo[20111:5046708] 2---{number = 1, name = main}

2018-02-23 20:45:57.993649+0800 YSC-GCD-demo[20111:5046708] 2---{number = 1, name = main}

2018-02-23 20:45:59.994928+0800 YSC-GCD-demo[20111:5046708] 3---{number = 1, name = main}

2018-02-23 20:46:01.995589+0800 YSC-GCD-demo[20111:5046708] 3---{number = 1, name = main}

在異步執(zhí)行 + 主隊(duì)列可以看到:

a.所有任務(wù)都是在當(dāng)前線程(主線程)中執(zhí)行的,并沒(méi)有開(kāi)啟新的線程(雖然異步執(zhí)行具備開(kāi)啟線程的能力,但因?yàn)槭侵麝?duì)列,所以所有任務(wù)都在主線程中)。

b.所有任務(wù)是在打印的syncConcurrent---begin和syncConcurrent---end之后才開(kāi)始執(zhí)行的(異步執(zhí)行不會(huì)做任何等待,可以繼續(xù)執(zhí)行任務(wù))。

c.任務(wù)是按順序執(zhí)行的(因?yàn)橹麝?duì)列是串行隊(duì)列,每次只有一個(gè)任務(wù)被執(zhí)行,任務(wù)一個(gè)接一個(gè)按順序執(zhí)行)。

弄懂了難理解、繞來(lái)繞去的隊(duì)列+任務(wù)之后,我們來(lái)學(xué)習(xí)一個(gè)簡(jiǎn)單的東西:5. GCD 線程間的通信。

總結(jié)

以上是生活随笔為你收集整理的c语言gcd 简易函数,简单[GCD]用法详细总结(上)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。