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

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

生活随笔

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

编程问答

GCD介绍(一): 基本概念和Dispatch Queue (转载)

發(fā)布時(shí)間:2024/4/17 编程问答 64 豆豆
生活随笔 收集整理的這篇文章主要介紹了 GCD介绍(一): 基本概念和Dispatch Queue (转载) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
什么是GCD?

Grand Central Dispatch或者GCD,是一套低層API,提供了一種新的方法來(lái)進(jìn)行并發(fā)程序編寫。從基本功能上講,GCD有點(diǎn)像 NSOperationQueue,他們都允許程序?qū)⑷蝿?wù)切分為多個(gè)單一任務(wù)然后提交至工作隊(duì)列來(lái)并發(fā)地或者串行地執(zhí)行。GCD比之 NSOpertionQueue更底層更高效,并且它不是Cocoa框架的一部分。

除了代碼的平行執(zhí)行能力,GCD還提供高度集成的事件控制系統(tǒng)。可以設(shè)置句柄來(lái)響應(yīng)文件描述符、mach ports(Mach port?用于 OS X上的進(jìn)程間通訊)、進(jìn)程、計(jì)時(shí)器、信號(hào)、用戶生成事件。這些句柄通過(guò)GCD來(lái)并發(fā)執(zhí)行。

GCD的API很大程度上基于block,當(dāng)然,GCD也可以脫離block來(lái)使用,比如使用傳統(tǒng)c機(jī)制提供函數(shù)指針和上下文指針。實(shí)踐證明,當(dāng)配合block使用時(shí),GCD非常簡(jiǎn)單易用且能發(fā)揮其最大能力。

你可以在Mac上敲命令“man dispatch”來(lái)獲取GCD的文檔。

為何使用?

GCD提供很多超越傳統(tǒng)多線程編程的優(yōu)勢(shì):

  • 易用:?GCD比之thread跟簡(jiǎn)單易用。由于GCD基于work unit而非像thread那樣基于運(yùn)算,所以GCD可以控制諸如等待任務(wù)結(jié)束、監(jiān)視文件描述符、周期執(zhí)行代碼以及工作掛起等任務(wù)。基于block的血統(tǒng)導(dǎo)致它能極為簡(jiǎn)單得在不同代碼作用域之間傳遞上下文。
  • 效率:?GCD被實(shí)現(xiàn)得如此輕量和優(yōu)雅,使得它在很多地方比之專門創(chuàng)建消耗資源的線程更實(shí)用且快速。這關(guān)系到易用性:導(dǎo)致GCD易用的原因有一部分在于你可以不用擔(dān)心太多的效率問(wèn)題而僅僅使用它就行了。
  • 性能:?GCD自動(dòng)根據(jù)系統(tǒng)負(fù)載來(lái)增減線程數(shù)量,這就減少了上下午切換以及增加了計(jì)算效率。
  • Dispatch Objects

    盡管GCD是純c語(yǔ)言的,但它被組建成面向?qū)ο蟮娘L(fēng)格。GCD對(duì)象被稱為dispatch object。Dispatch object像Cocoa對(duì)象一樣是引用計(jì)數(shù)的。使用dispatch_release和dispatch_retain函數(shù)來(lái)操作dispatch object的引用計(jì)數(shù)來(lái)進(jìn)行內(nèi)存管理。但主意不像Cocoa對(duì)象,dispatch object并不參與垃圾回收系統(tǒng),所以即使開啟了GC,你也必須手動(dòng)管理GCD對(duì)象的內(nèi)存。

    Dispatch queues 和 dispatch sources(后面會(huì)介紹到)可以被掛起和恢復(fù),可以有一個(gè)相關(guān)聯(lián)的任意上下文指針,可以有一個(gè)相關(guān)聯(lián)的任務(wù)完成觸發(fā)函數(shù)。可以查閱“man dispatch_object”來(lái)獲取這些功能的更多信息。

    Dispatch Queues

    GCD的基本概念就是dispatch queue。dispatch queue是一個(gè)對(duì)象,它可以接受任務(wù),并將任務(wù)以先到先執(zhí)行的順序來(lái)執(zhí)行。dispatch queue可以是并發(fā)的或串行的。并發(fā)任務(wù)會(huì)像NSOperationQueue那樣基于系統(tǒng)負(fù)載來(lái)合適地并發(fā)進(jìn)行,串行隊(duì)列同一時(shí)間只執(zhí)行單一任務(wù)。

    GCD中有三種隊(duì)列類型:

  • The main queue:?與主線程功能相同。實(shí)際上,提交至main queue的任務(wù)會(huì)在主線程中執(zhí)行。main queue可以調(diào)用dispatch_get_main_queue()來(lái)獲得。因?yàn)閙ain queue是與主線程相關(guān)的,所以這是一個(gè)串行隊(duì)列。
  • Global queues:?全局隊(duì)列是并發(fā)隊(duì)列,并由整個(gè)進(jìn)程共享。進(jìn)程中存在三個(gè)全局隊(duì)列:高、中(默認(rèn))、低三個(gè)優(yōu)先級(jí)隊(duì)列。可以調(diào)用dispatch_get_global_queue函數(shù)傳入優(yōu)先級(jí)來(lái)訪問(wèn)隊(duì)列。
  • 用戶隊(duì)列:?用戶隊(duì)列 (GCD并不這樣稱呼這種隊(duì)列, 但是沒(méi)有一個(gè)特定的名字來(lái)形容這種隊(duì)列,所以我們稱其為用戶隊(duì)列) 是用函數(shù)?dispatch_queue_create?創(chuàng)建的隊(duì)列. 這些隊(duì)列是串行的。正因?yàn)槿绱?#xff0c;它們可以用來(lái)完成同步機(jī)制, 有點(diǎn)像傳統(tǒng)線程中的mutex。
  • 創(chuàng)建隊(duì)列

    要使用用戶隊(duì)列,我們首先得創(chuàng)建一個(gè)。調(diào)用函數(shù)dispatch_queue_create就行了。函數(shù)的第一個(gè)參數(shù)是一個(gè)標(biāo)簽,這純是為了 debug。Apple建議我們使用倒置域名來(lái)命名隊(duì)列,比如“com.dreamingwish.subsystem.task”。這些名字會(huì)在崩潰日 志中被顯示出來(lái),也可以被調(diào)試器調(diào)用,這在調(diào)試中會(huì)很有用。第二個(gè)參數(shù)目前還不支持,傳入NULL就行了。

    提交 Job

    向一個(gè)隊(duì)列提交Job很簡(jiǎn)單:調(diào)用dispatch_async函數(shù),傳入一個(gè)隊(duì)列和一個(gè)block。隊(duì)列會(huì)在輪到這個(gè)block執(zhí)行時(shí)執(zhí)行這個(gè)block的代碼。下面的例子是一個(gè)在后臺(tái)執(zhí)行一個(gè)巨長(zhǎng)的任務(wù):

    1 2 3 4 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ ????????[self goDoSomethingLongAndInvolved]; ????????NSLog(@"Done doing something long and involved"); });

    dispatch_async?函數(shù)會(huì)立即返回, block會(huì)在后臺(tái)異步執(zhí)行。?

    當(dāng)然,通常,任務(wù)完成時(shí)簡(jiǎn)單地NSLog個(gè)消息不是個(gè)事兒。在典型的Cocoa程序中,你很有可能希望在任務(wù)完成時(shí)更新界面,這就意味著需要在主線 程中執(zhí)行一些代碼。你可以簡(jiǎn)單地完成這個(gè)任務(wù)——使用嵌套的dispatch,在外層中執(zhí)行后臺(tái)任務(wù),在內(nèi)層中將任務(wù)dispatch到main queue:

    1 2 3 4 5 6 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ ????????[self goDoSomethingLongAndInvolved]; ????????dispatch_async(dispatch_get_main_queue(), ^{ ????????????[textField setStringValue:@"Done doing something long and involved"]; ????????}); });

    還有一個(gè)函數(shù)叫dispatch_sync,它干的事兒和dispatch_async相同,但是它會(huì)等待block中的代碼執(zhí)行完成并返回。結(jié)合 __block類型修飾符,可以用來(lái)從執(zhí)行中的block獲取一個(gè)值。例如,你可能有一段代碼在后臺(tái)執(zhí)行,而它需要從界面控制層獲取一個(gè)值。那么你可以使 用dispatch_sync簡(jiǎn)單辦到:

    1 2 3 4 5 6 7 8 __block NSString *stringValue; dispatch_sync(dispatch_get_main_queue(), ^{ ????????// __block variables aren't automatically retained ????????// so we'd better make sure we have a reference we can keep ????????stringValue = [[textField stringValue] copy]; }); [stringValue autorelease]; // use stringValue in the background now

    我們還可以使用更好的方法來(lái)完成這件事——使用更“異步”的風(fēng)格。不同于取界面層的值時(shí)要阻塞后臺(tái)線程,你可以使用嵌套的block來(lái)中止后臺(tái)線程,然后從主線程中獲取值,然后再將后期處理提交至后臺(tái)線程:

    dispatch_queue_t bgQueue = myQueue;dispatch_async(dispatch_get_main_queue(), ^{NSString *stringValue = [[[textField stringValue] copy] autorelease];dispatch_async(bgQueue, ^{// use stringValue in the background now});});

    取決于你的需求,myQueue可以是用戶隊(duì)列也可以使全局隊(duì)列。

    ?

    不再使用鎖(Lock)

    用戶隊(duì)列可以用于替代鎖來(lái)完成同步機(jī)制。在傳統(tǒng)多線程編程中,你可能有一個(gè)對(duì)象要被多個(gè)線程使用,你需要一個(gè)鎖來(lái)保護(hù)這個(gè)對(duì)象:

    NSLock *lock;

    訪問(wèn)代碼會(huì)像這樣:

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 - (id)something { ????id localSomething; ????[lock lock]; ????localSomething = [[something retain] autorelease]; ????[lock unlock]; ????return localSomething; } - (void)setSomething:(id)newSomething { ????[lock lock]; ????if(newSomething != something) ????{ ????????[something release]; ????????something = [newSomething retain]; ????????[self updateSomethingCaches]; ????} ????[lock unlock]; }

    使用GCD,可以使用queue來(lái)替代:

    dispatch_queue_t queue;

    要用于同步機(jī)制,queue必須是一個(gè)用戶隊(duì)列,而非全局隊(duì)列,所以使用usingdispatch_queue_create初始化一個(gè)。然后可以用dispatch_async?或者?dispatch_sync將共享數(shù)據(jù)的訪問(wèn)代碼封裝起來(lái):

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 - (id)something { ????__block id localSomething; ????dispatch_sync(queue, ^{ ????????localSomething = [something retain]; ????}); ????return [localSomething autorelease]; } - (void)setSomething:(id)newSomething { ????dispatch_async(queue, ^{ ????????if(newSomething != something) ????????{ ????????????[something release]; ????????????something = [newSomething retain]; ????????????[self updateSomethingCaches]; ????????} ????}); }

    ?值得注意的是dispatch queue是非常輕量級(jí)的,所以你可以大用特用,就像你以前使用lock一樣。

    現(xiàn)在你可能要問(wèn):“這樣很好,但是有意思嗎?我就是換了點(diǎn)代碼辦到了同一件事兒。”

    實(shí)際上,使用GCD途徑有幾個(gè)好處:

  • 平行計(jì)算:?注意在第二個(gè)版本的代碼中,?-setSomething:是怎么使用dispatch_async的。調(diào)用?-setSomething:會(huì)立即返回,然后這一大堆工作會(huì)在后臺(tái)執(zhí)行。如果updateSomethingCaches是一個(gè)很費(fèi)時(shí)費(fèi)力的任務(wù),且調(diào)用者將要進(jìn)行一項(xiàng)處理器高負(fù)荷任務(wù),那么這樣做會(huì)很棒。
  • 安全:?使用GCD,我們就不可能意外寫出具有不成對(duì)Lock的代碼。在常規(guī)Lock代碼中,我們很可能在解鎖之前讓代碼返回了。使用GCD,隊(duì)列通常持續(xù)運(yùn)行,你必將歸還控制權(quán)。
  • 控制:?使用GCD我們可以掛起和恢復(fù)dispatch queue,而這是基于鎖的方法所不能實(shí)現(xiàn)的。我們還可以將一個(gè)用戶隊(duì)列指向另一個(gè)dspatch queue,使得這個(gè)用戶隊(duì)列繼承那個(gè)dispatch queue的屬性。使用這種方法,隊(duì)列的優(yōu)先級(jí)可以被調(diào)整——通過(guò)將該隊(duì)列指向一個(gè)不同的全局隊(duì)列,若有必要的話,這個(gè)隊(duì)列甚至可以被用來(lái)在主線程上執(zhí)行 代碼。
  • 集成:?GCD的事件系統(tǒng)與dispatch queue相集成。對(duì)象需要使用的任何事件或者計(jì)時(shí)器都可以從該對(duì)象的隊(duì)列中指向,使得這些句柄可以自動(dòng)在該隊(duì)列上執(zhí)行,從而使得句柄可以與對(duì)象自動(dòng)同步。
  • 總結(jié)

    現(xiàn)在你已經(jīng)知道了GCD的基本概念、怎樣創(chuàng)建dispatch queue、怎樣提交Job至dispatch queue以及怎樣將隊(duì)列用作線程同步。接下來(lái)我會(huì)向你展示如何使用GCD來(lái)編寫平行執(zhí)行代碼來(lái)充分利用多核系統(tǒng)的性能^ ^。我還會(huì)討論GCD更深層的東西,包括事件系統(tǒng)和queue targeting。

    ?

    ?

    原文:http://www.dreamingwish.com/dream-2012/of-of-of-of-gcd-introduced-1-basic-concepts-in-and-the-dispatch-queue.html

    轉(zhuǎn)載于:https://www.cnblogs.com/liushanshan/archive/2013/02/05/2893024.html

    總結(jié)

    以上是生活随笔為你收集整理的GCD介绍(一): 基本概念和Dispatch Queue (转载)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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