Objective-C iOS多線程之GCD深入理解

在 GCD 中,加入了兩個非常重要的概念:任務(wù)和隊列
一個線程是可以擁有多個執(zhí)行隊列的,所有任務(wù)是添加到隊列中等待執(zhí)行的
主隊列是特殊的串行隊列,自己創(chuàng)建的隊列可以指定串行或并行,全局隊列是并行隊列
任務(wù):即操作,你想要干什么,說白了就是一段代碼,在 GCD 中就是一個 Block,所以添加任務(wù)十分方便。
任務(wù)有兩種執(zhí)行方式: 同步執(zhí)行和異步執(zhí)行,他們之間的區(qū)別主要在于會不會阻塞當(dāng)前線程
首先看下面這兩個例子:
1、

dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
NSLog(@"%d",[[NSThread currentThread] isMainThread]);
});

2、

dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
NSLog(@"%d",[[NSThread currentThread] isMainThread]);
});

兩個例子都是創(chuàng)建一個新隊列,之間的區(qū)別只在于前者是以同步運行,后者則是異步結(jié)果前者打印出1,后者則是0。
我們分析一下,這里同步的意思其實是對于線程的所有執(zhí)行隊列而言,就是說同步執(zhí)行時,除了block任務(wù),在同一個線程執(zhí)行的其他隊列全部暫停執(zhí)行,當(dāng)block任務(wù)執(zhí)行完成后,其他隊列任務(wù)才恢復(fù)執(zhí)行。(這里還有個要特別注意的,就是系統(tǒng)在判別是否要暫停隊列的執(zhí)行時,是按照block任務(wù)是否在隊列頭,如果不是就停止隊列執(zhí)行)
上面例子1中創(chuàng)建一個新隊列,block任務(wù)在第一個,即隊列頭,以同步執(zhí)行時就是所有在主線程執(zhí)行的隊列會暫停執(zhí)行(除了block任務(wù)所在隊列)。例子2因為是創(chuàng)建一個新隊列,又是異步執(zhí)行,所以會創(chuàng)建一個新線程執(zhí)行,所以打印出來的0,也就是主線程上的隊列照常執(zhí)行。

為了證明我上面的假設(shè),我舉個例子:
3、

dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync(queue, ^{
NSLog(@"%d",[[NSThread currentThread] isMainThread]);
});

4、

dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_async(queue, ^{
NSLog(@"%d",[[NSThread currentThread] isMainThread]);
});

上面兩個例子都是將block任務(wù)添加到主隊列,但是結(jié)果卻不同,例子3結(jié)果是永遠不會執(zhí)行打印語句,程序不會再執(zhí)行了,例子4正常執(zhí)行,且在主隊列中
結(jié)論:不是異步就一定會開啟新的線程

例子3因為將block任務(wù)添加到主隊列中,此時主隊列還有任務(wù)(viewDidLoad沒有執(zhí)行完,所以block任務(wù)不是將要執(zhí)行的任務(wù)),根據(jù)前面的系統(tǒng)判定,主隊列被暫停執(zhí)行,此時前面的任務(wù)無法完成,后面的block任務(wù)也無法完成,造成死循環(huán)例子4中將任務(wù)添加到主隊列中,雖然是異步操作,但是并不會開啟新的線程,因為在主隊列中,要在主線程中執(zhí)行,而異步操作不會將線程阻塞,所以隊列照常執(zhí)行。

結(jié)論:同步會讓系統(tǒng)判定暫停執(zhí)行所有不以block塊任務(wù)為第一任務(wù)的隊列(即如果block塊任務(wù)不在隊列頭,那么block塊任務(wù)所在的隊列也會暫停執(zhí)行),且同步一定不會開啟新線程,因為GCD覺得既然其它隊列暫停執(zhí)行,block塊任務(wù)就可以在當(dāng)前線程執(zhí)行了,沒有必要開啟新線程。而異步則系統(tǒng)不會進行判定,但是不一定會開啟新線程,這個跟隊列有關(guān),如果是新創(chuàng)建的隊列,那么GCD就會開啟新線程,如果加入已有的隊列,那么就會在隊列所在的線程中執(zhí)行。

簡單來講,同步操作那么block塊任務(wù)會在當(dāng)前線程中執(zhí)行,比如上面在主線程中進行同步操作,那么一定就是在主線程中執(zhí)行,不管隊列是主隊列還是全局隊列或者自己創(chuàng)建的隊列。如果是異步操作的話,那么就要分情況來看了,如果是主隊列,那么就是在主線程中執(zhí)行,如果是全局或自己創(chuàng)建的隊列,那么就是在新創(chuàng)建的線程中執(zhí)行,全局隊列會根據(jù)任務(wù)自動創(chuàng)建一個或多個線程,自己創(chuàng)建的隊列就是根據(jù)參數(shù)設(shè)定和任務(wù)進行分配。

至于串行和并行,串行和并行是針對同一個隊列中的任務(wù)而言的,當(dāng)使用串行,那么隊列里的那么隊列里的任務(wù)最多只能使用一個線程運行,即同一時刻只有一個任務(wù)在執(zhí)行,如果是并行,那么系統(tǒng)會根據(jù)隊列里的任務(wù)自動分配線程執(zhí)行,最大線程數(shù)根據(jù)參數(shù)設(shè)定


轉(zhuǎn)載請注明:作者SmithJackyson

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

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

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