iOS初級編程之GCD的簡單使用

?????? GCD的簡述就不過多強(qiáng)調(diào)了(網(wǎng)上一搜一大把?。┻@篇文章主要是記錄和學(xué)習(xí)GCD并學(xué)會簡單調(diào)用。希望能對大家有所幫助,如果有不對的地方還請指出,多謝大家!

GCD主要分為三種隊(duì)列和隊(duì)列組:

The Main queue (主線程隊(duì)列)

Global queue(全局并發(fā)隊(duì)列)

Custom queue(自定義隊(duì)列)

Group queue(隊(duì)列組)


主線程隊(duì)列

1.獲取主線程串行隊(duì)列

?dispatch_queue_t queue = dispatch_get_main_queue();

2.異步請求

NSLog(@"1");

dispatch_async(queue, ^{

NSLog(@"異步操作");

});

NSLog(@"2");

3.輸出結(jié)果為:

由此可見在主線程輸出@"1"和@"2",異步輸出@"異步操作"。


4.但是當(dāng)我們用主線程串行隊(duì)列的時候,使用同步執(zhí)行時:


出現(xiàn)線程死鎖問題,那么什么是線程死鎖呢?

死鎖即為:兩個或多個線程相互等待,導(dǎo)致一個線程都不進(jìn)行然后程序卡死。


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

1.這種隊(duì)列主要分為四個優(yōu)先級:

dispatch_queue_t globalDefault = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_queue_t globalHigh = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);

dispatch_queue_t globalLow = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);

dispatch_queue_t globalBackGround = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);

雖然分為四個優(yōu)先級,但是他們直接不是絕對的由高到低且全是并發(fā)操作,只是DEFAULT和HIGH的執(zhí)行順序要略高于LOW和BACKGROUND。

默認(rèn)都為DISPATCH_QUEUE_PRIORITY_DEFAULT,而第二個參數(shù)也默認(rèn)傳0

2.實(shí)現(xiàn)同步:

NSLog(@"1");

dispatch_queue_t globalDefault = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_sync(globalDefault, ^{

NSLog(@"2");

});

NSLog(@"3");

3.輸出:

4.全局并發(fā)隊(duì)列的異步和主線程串行隊(duì)列的用法基本一致,但是有一點(diǎn)區(qū)別就是當(dāng)全局并發(fā)隊(duì)列大量異步操作的時候會出現(xiàn)一種問題:

4.1 當(dāng)我們大量異步請求的時候:

NSLog(@"1");

dispatch_queue_t globalDefault = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_async(globalDefault, ^{

NSLog(@"2");

});

//大量異步請求

...

dispatch_async(globalDefault, ^{

NSLog(@"2");

});

NSLog(@"3");

4.2 輸出結(jié)果為:

可以看到我們在主線程輸出@"1"和@"3"的時候用全局并發(fā)隊(duì)列添加了很多異步請求,這個時候子線程卻不等主線程運(yùn)行完畢就先運(yùn)行了!

4.3 這和 全局并發(fā)隊(duì)列 不同,主線程串行隊(duì)列 這種主線程隊(duì)列是一定要等到主線程運(yùn)行完畢后在進(jìn)行異步操作:

NSLog(@"1");

dispatch_queue_t queue = dispatch_get_main_queue();

dispatch_async(queue, ^{

NSLog(@"2");

});

...

dispatch_async(queue, ^{

NSLog(@"2");

});

NSLog(@"3");

4.4 輸出:


4.5 總結(jié):

?????? 因?yàn)橹骶€程隊(duì)列一定是等待主線程運(yùn)行完再執(zhí)行block里面的操作。但是主線程中卻是同步操作,所以主線程等待主線程隊(duì)列同步請求,而主線程隊(duì)列卻要等待主線程運(yùn)行完,出現(xiàn)了兩個線程相互等待造成死鎖。


自定義隊(duì)列 Custom queue

1. 自定義隊(duì)列可以自己設(shè)置串行和并行,第一個參數(shù)只是一個編輯名稱,第二個參數(shù)設(shè)置自定義隊(duì)列的串行和并行。

//串行 dispatch_queue_t queueSerial = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);

//并行 dispatch_queue_t queueConcurrent = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);

2.1.1 串行隊(duì)列的同步請求:

NSLog(@"1");

dispatch_queue_t queueSerial = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);

dispatch_sync(queueSerial, ^{

NSLog(@"2");

});

NSLog(@"3");

2.1.2 輸出:

注意!串行隊(duì)列同步請求不能嵌套,這樣會導(dǎo)致線程死鎖。

2.1.3 串行隊(duì)列的異步操作是可以嵌套的:

NSLog(@"1");

dispatch_queue_t queueSerial = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);

dispatch_async(queueSerial, ^{

???????????? NSLog(@"2");

???????????? dispatch_async(queueSerial, ^{

?????????????????????? NSLog(@"3");

????????????? });

});

NSLog(@"4");

2.1.4 輸出:

2.1.5 如果有耗時操作的話,串行隊(duì)列會按順序等待前面先完成,會造成界面卡頓:

NSLog(@"1");

dispatch_queue_t queueSerial = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);

dispatch_async(queueSerial, ^{

sleep(1);

NSLog(@"2");

});

dispatch_async(queueSerial, ^{

NSLog(@"3");

});

NSLog(@"4");

2.1.6 輸出:

??????? 從時間上來看,先輸出@"1"和@"4",延時1S之后執(zhí)行@"2"和@"3",并且@"3"要等待@"2"輸出后才能輸出。

2.2.1 下面是并聯(lián)同步,并聯(lián)同步是可以嵌套的:

NSLog(@"1");

dispatch_queue_t queueConcurrent = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);

dispatch_sync(queueConcurrent, ^{

?????????? NSLog(@"2");

?????????? dispatch_sync(queueConcurrent, ^{

????????????????????? NSLog(@"3");

??????????? });

});

NSLog(@"4");

2.2.2 輸出:

2.2.3 并行隊(duì)列的要是操作不用等待前面線程執(zhí)行完:

NSLog(@"1");

dispatch_queue_t queueConcurrent = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);

dispatch_async(queueConcurrent, ^{

sleep(1);

NSLog(@"2");

});

dispatch_async(queueConcurrent, ^{

NSLog(@"3");

});

NSLog(@"4");

2.2.4 輸出:

?????? 并聯(lián)異步操作先執(zhí)行主線程@"1"和@"4"操作,之后執(zhí)行@"2"和@"3"但是由于@"2"是耗時操作,所以@"3"不用等待@"2"執(zhí)行完在執(zhí)行。



線程組

1. 創(chuàng)建一個線程組

dispatch_group_t group = dispatch_group_create();

2. 使用線程組

NSLog(@"1");

dispatch_group_t group = dispatch_group_create();

dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);

dispatch_group_async(group, queue, ^{

sleep(1);

NSLog(@"3");

});

dispatch_group_notify(group, queue, ^{

NSLog(@"線程執(zhí)行完畢");

});

NSLog(@"2");

3. 輸出:

?????? dispatch_group_notify 用于監(jiān)聽線程組是否全部執(zhí)行完畢,如果執(zhí)行完畢,執(zhí)行Block里面的代碼。

線程等待時間

1. 聲明一個線程時間

dispatch_time_t Time = dispatch_time(DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC);

?????? 第一個參數(shù)默認(rèn)是DISPATCH_TIME_NOW從現(xiàn)在開始,第二個參數(shù)是時間參數(shù)(參數(shù))*NSEC_PER_SEC。

2. 使用時間線程,延時操作:

NSLog(@"1");

dispatch_time_t Time = dispatch_time(DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC);

dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);

dispatch_after(Time,queue, ^{

NSLog(@"2");

});

NSLog(@"3");

3. 輸出:


這次就寫這么多把,初級GCD(一)就寫這么多,寫的不好請多包涵。

特別感謝 http://www.itdecent.cn/p/ae786a4cf3b1? 這篇文章。還有好多網(wǎng)上無私的奉獻(xiàn)者。

這是本人的第一篇文章,以后還要繼續(xù)努力。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容