99精品伊人亚洲|最近国产中文炮友|九草在线视频支援|AV网站大全最新|美女黄片免费观看|国产精品资源视频|精彩无码视频一区|91大神在线后入|伊人终合在线播放|久草综合久久中文

您好,歡迎來電子發(fā)燒友網(wǎng)! ,新用戶?[免費(fèi)注冊(cè)]

您的位置:電子發(fā)燒友網(wǎng)>源碼下載>通訊/手機(jī)編程>

iOS并發(fā)編程中Dispatch Queues的創(chuàng)建與管理的實(shí)踐總結(jié)

大小:0.2 MB 人氣: 2017-10-11 需要積分:1
 導(dǎo)讀:本文為讀《Concurrency Programming Guide》筆記第二篇,在上篇分享了OS X和iOS應(yīng)用開發(fā)中實(shí)現(xiàn)任務(wù)異步執(zhí)行的技術(shù)以及應(yīng)注意的事項(xiàng)之后,作者付宇軒(@DevTalking)對(duì)Operation對(duì)象的設(shè)置與執(zhí)行,以及Dispatch Queues的創(chuàng)建與管理進(jìn)行了實(shí)踐總結(jié)。
  系列閱讀
  Operation對(duì)象的相關(guān)設(shè)置
  Operation對(duì)象除了上文中講到到基本使用方法外還有一些其他的特性,這些特性需要根據(jù)我們的應(yīng)用場(chǎng)景去設(shè)置,設(shè)置的時(shí)機(jī)在創(chuàng)建Operation對(duì)象之后和運(yùn)行它或者將其放入操作隊(duì)列之前,下面讓我們來看看Operation對(duì)象還有哪些特性。
  Operation對(duì)象之間的依賴
  與GCD不同,Operation Queue不遵循先進(jìn)先出的原則,而且Operation Queue始終是并發(fā)執(zhí)行Operation對(duì)象的,所以想讓Operation對(duì)象串行執(zhí)行就需要用它的Operation對(duì)象依賴特性,該特性可以讓Operation對(duì)象將自己與另外一個(gè)Operation對(duì)象進(jìn)行關(guān)聯(lián),并且當(dāng)關(guān)聯(lián)的Operation對(duì)象執(zhí)行完成后才可以執(zhí)行,這樣就達(dá)到了串行執(zhí)行Operation對(duì)象的目的。
  我們可以用NSOperation的addDependency方法添加依賴的Operation對(duì)象,而且產(chǎn)生依賴的這兩個(gè)Operation對(duì)象并不要求必須在相同的操作隊(duì)列中,但是這種依賴只能是單向的,不能相互依賴。
  importFoundation classTestOperationDependency{func launch() { letblockOperationA = NSBlockOperation(block: { print(“Task in blockOperationA.。.”) sleep(3) }) letblockOperationB = NSBlockOperation(block: { print(“Task in blockOperationB.。.”) sleep(5) }) blockOperationA.addDependency(blockOperationB) letoperationQueue = NSOperationQueue() operationQueue.addOperation(blockOperationA) operationQueue.addOperation(blockOperationB) sleep(10) } } lettestOperationDependency = TestOperationDependency() testOperationDependency.launch()
  上面的示例代碼展示了如何給Operation對(duì)象添加依賴,大家可以注釋掉blockOperationA.addDependency(blockOperationB)這一行看看打印結(jié)果有什么區(qū)別。
  Operation對(duì)象的優(yōu)先級(jí)
  上文中說了,操作隊(duì)列里的Operation對(duì)象都是并發(fā)執(zhí)行的,如果一個(gè)操作隊(duì)列中有多個(gè)Operation對(duì)象,那么誰(shuí)先執(zhí)行誰(shuí)后執(zhí)行取決于Operation對(duì)象的依賴Operation對(duì)象是否已執(zhí)行完成,也就是是否處于準(zhǔn)備執(zhí)行的狀態(tài)。其實(shí)Operation對(duì)象自身也有優(yōu)先級(jí)的屬性,如果有兩個(gè)都處于準(zhǔn)備執(zhí)行狀態(tài)的Operation對(duì)象,那么優(yōu)先級(jí)高的會(huì)先執(zhí)行,優(yōu)先級(jí)低的后執(zhí)行。每個(gè)Operation對(duì)象默認(rèn)的優(yōu)先級(jí)是NSOperationQueuePriority.Normal級(jí)別,我們可以通過設(shè)置queuePriority屬性更改Operation的在隊(duì)列中執(zhí)行的優(yōu)先級(jí),優(yōu)先級(jí)別有以下五種:
  NSOperationQueuePriority.Normal:正常優(yōu)先級(jí)NSOperationQueuePriority.Low:低優(yōu)先級(jí)NSOperationQueuePriority.VeryLow:非常低優(yōu)先級(jí)NSOperationQueuePriority.High:高優(yōu)先級(jí)NSOperationQueuePriority.VeryHigh:非常高優(yōu)先級(jí)
  這里我們需要注意一下Operation對(duì)象優(yōu)先級(jí)的作用域,它只能作用于相同的操作隊(duì)列中,不同操作隊(duì)列中的Operation對(duì)象是不受優(yōu)先級(jí)影響的。另外需要注意的是,如果有兩個(gè)Operation對(duì)象,一個(gè)處于準(zhǔn)備執(zhí)行狀態(tài),但優(yōu)先級(jí)比較低,另一個(gè)處于等待狀態(tài),但優(yōu)先級(jí)比較高,那么此時(shí)仍然是處于準(zhǔn)備執(zhí)行狀態(tài)的低優(yōu)先級(jí)Operation對(duì)象先執(zhí)行??梢奜peration對(duì)象的優(yōu)先級(jí)相互影響需要滿足兩個(gè)條件,一是必須處在同一個(gè)操作隊(duì)列中,另一個(gè)是Operation對(duì)象都處于準(zhǔn)備執(zhí)行狀態(tài)。
  通過Operation對(duì)象修改線程優(yōu)先級(jí)
  通常情況下,線程的優(yōu)先級(jí)由內(nèi)核自己管理,不過在OS X v10.6及以后的版本和iOS4到iOS7期間,NSOperation多了一個(gè)threadPriority屬性,我們可以通過該屬性設(shè)置Operation對(duì)象運(yùn)行所在線程的優(yōu)先級(jí),數(shù)值范圍為0.0到1.0,數(shù)字越高優(yōu)先級(jí)越高。不過可能是出于線程安全等方面的考慮,Apple從iOS8開始廢除了該屬性。
  設(shè)置Completion Block
  上篇文章中說過,Operation對(duì)象其中的一個(gè)特別好的特性就是完成時(shí)回調(diào)閉包Completion Block。它的作用不言而喻,就是當(dāng)主要任務(wù)執(zhí)行完成之后做一些收尾的處理工作,我們可以設(shè)置completionBlock屬性給Operation對(duì)象添加完成時(shí)回調(diào)閉包:
  blockOperationA.completionBlock = { print(“blockOperationA has finished.。.”) }
  執(zhí)行Operation對(duì)象
  雖然前面文章的示例中已經(jīng)包含了對(duì)Operation對(duì)象的執(zhí)行,但是并沒詳細(xì)說明,這節(jié)就說說Operation對(duì)象的執(zhí)行。
  使用Operation Queue
  使用Operation Queue操作隊(duì)列執(zhí)行Operation對(duì)象已然是標(biāo)配選項(xiàng)了,操作隊(duì)列在Cocoa框架中對(duì)應(yīng)的類是NSOperationQueue,一個(gè)操作隊(duì)列中可以添加多個(gè)Operation對(duì)象,但一次到底添加多少Operation對(duì)象得根據(jù)實(shí)際情況而定,比如應(yīng)用程序?qū)?nèi)存的消耗情況、內(nèi)核的空閑情況等,所以說凡事得有度,不然反而會(huì)適得其反。另外需要注意的一點(diǎn)是不論有多少個(gè)操作隊(duì)列,它們都受制于系統(tǒng)的負(fù)載、內(nèi)核空閑等運(yùn)行情況,所以說并不是說再創(chuàng)建一個(gè)操作隊(duì)列就能執(zhí)行更多的Operation對(duì)象。
  在使用操作隊(duì)列時(shí),我們首先要?jiǎng)?chuàng)建NSOperationQueue的實(shí)例:
  letoperationQueue = NSOperationQueue()
  然后通過NSOperationQueue的addOperation方法添加Operation對(duì)象:
  operationQueue.addOperation(blockOperationA) operationQueue.addOperation(blockOperationB)
  在OS X v10.6之后和iOS4之后,我們還可以用addOperations:waitUntilFinished:方法添加一組Operation對(duì)象:
  operationQueue.addOperations([blockOperationA, blockOperationB], waitUntilFinished: false)
  該方法有兩個(gè)參數(shù)
  ops: [NSOperation]:Operation對(duì)象數(shù)組。waitUntilFinished wait: Bool:該參數(shù)標(biāo)示這個(gè)操作隊(duì)列在執(zhí)行Operation對(duì)象時(shí)是否會(huì)阻塞當(dāng)前線程。
  我們還可以通過addOperationWithBlock方法向操作隊(duì)列中直接添加閉包,而不需要去創(chuàng)建Operation對(duì)象:
  operationQueue.addOperationWithBlock({ print(“The block is running in Operation Queue.。.”) })
  除了以上這幾種添加Operation對(duì)象的方法外,還可以通過NSOperationQueue的maxConcurrentOperationCount屬性設(shè)置同時(shí)執(zhí)行Operation對(duì)象的最大數(shù):
  operationQueue.maxConcurrentOperationCount =2
  如果設(shè)置為1,那么不管該操作隊(duì)列中添加了多少Operation對(duì)象,每次都只運(yùn)行一個(gè),而且會(huì)按照添加Operation對(duì)象的順序去執(zhí)行。所以如果遇到添加到操作的隊(duì)列的Operation對(duì)象延遲執(zhí)行了,那么通常會(huì)有兩個(gè)原因:
  添加的Operation對(duì)象數(shù)超過了操作隊(duì)列設(shè)置的同時(shí)執(zhí)行Operation對(duì)象的最大數(shù)。延遲執(zhí)行的Operation對(duì)象在等待它依賴的Operation對(duì)象執(zhí)行完成。
  另外需要的注意的是當(dāng)Operation對(duì)象添加到操作隊(duì)列中后,不要再更改它任務(wù)中涉及到的任何屬性或者它的依賴,因?yàn)榈讲僮麝?duì)列中的Operation對(duì)象隨時(shí)會(huì)被執(zhí)行,所以如果你自以為它還沒有被執(zhí)行而去修改它,可能并不會(huì)達(dá)到你想要的結(jié)果。
  手動(dòng)執(zhí)行Operation對(duì)象
  除了用操作隊(duì)列來執(zhí)行Operation對(duì)象以外,我們還可以手動(dòng)執(zhí)行某個(gè)Operation對(duì)象,但是這需要我們注意更多的細(xì)節(jié)問題,也要寫更多的代碼去確保Operation對(duì)象能正確執(zhí)行。在上篇文章中,我們創(chuàng)建過自定義的Operation對(duì)象,其中我們知道有幾個(gè)屬性特別需要我們注意,那就是ready、concurrent、executing、finished、cancelled,對(duì)應(yīng)Operation對(duì)象是否出于準(zhǔn)備執(zhí)行狀態(tài)、是否為異步并發(fā)執(zhí)行的、是否正在執(zhí)行、是否已經(jīng)執(zhí)行完成、是否已被終止。
  這些狀態(tài)在我們使用操作隊(duì)列時(shí)都不需要理會(huì),都有操作隊(duì)列幫我們把控判斷,確保Operation對(duì)象的正確執(zhí)行,我們只需要在必要的時(shí)候獲取狀態(tài)信息查看而已。但是如果手動(dòng)執(zhí)行Operation對(duì)象,那么這些狀態(tài)都需要我們來把控,因?yàn)槟闶謩?dòng)執(zhí)行一個(gè)Operation對(duì)象時(shí)要判斷它的依賴對(duì)象是否執(zhí)行完成,是否被終止了等等,所以并不是簡(jiǎn)單的調(diào)用start方法,下面來看看如果正確的手動(dòng)執(zhí)行Operation對(duì)象:
  func performOperation(operation: NSOperation)-》Bool { varresult = falseifoperation.ready && !operation.cancelled { ifoperation.concurrent { operation.start() } else{ NSThread.detachNewThreadSelector(“start”, toTarget: operation, withObject: nil) } result = true} returnresult }
  終止Operation對(duì)象執(zhí)行
  一旦Operation對(duì)象被添加到操作隊(duì)列中,這個(gè)Operation對(duì)象就屬于這個(gè)操作隊(duì)列了,并且不能被移除,唯一能讓Operation對(duì)象失效的方法就是通過NSOperation的cancel方法終止它執(zhí)行,或者也可以通過NSOperationQueue的cancelAllOperations方法終止在隊(duì)列中的所有Operation對(duì)象。
  暫停和恢復(fù)操作隊(duì)列
  在實(shí)際運(yùn)用中,如果我們希望暫停操作隊(duì)列執(zhí)行Operation對(duì)象,可以通過設(shè)置NSOperationQueue的suspended屬性為false來實(shí)現(xiàn),不過這里要注意的是暫停操作隊(duì)列只是暫停執(zhí)行下一個(gè)Operation對(duì)象,而不是暫停當(dāng)前正在執(zhí)行的Operation對(duì)象,將suspended屬性設(shè)置為true后,操作隊(duì)列則恢復(fù)執(zhí)行。
  Dispatch Queues
  Dispatch Queue是GCD中的核心功能,它能讓我們很方便的異步或同步執(zhí)行任何被封裝為閉包的任務(wù),它的運(yùn)作模式與Operation Queue很相似,但是有一點(diǎn)不同的是Dispatch Queue是一種先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu),也就是執(zhí)行任務(wù)的順序永遠(yuǎn)等同于添加任務(wù)時(shí)的順序。GCD中已經(jīng)為我們提供了幾種類型的Dispatch Queue,當(dāng)然我們也可以根據(jù)需求自己創(chuàng)建Dispatch Queue,下面我們先來看看Dispatch Queue的類型:
  串行Dispatch Queue:該類型的隊(duì)列一次只能執(zhí)行一個(gè)任務(wù),當(dāng)前任務(wù)完成之后才能執(zhí)行下一個(gè)任務(wù),而且可依任務(wù)的不同而在不同的線程中執(zhí)行,這類隊(duì)列通常作為私有隊(duì)列使用。這里需要注意的是雖然該類型的隊(duì)列一次只能執(zhí)行一個(gè)任務(wù),但是可以讓多個(gè)串行隊(duì)列同時(shí)開始執(zhí)行任務(wù),達(dá)到并發(fā)執(zhí)行的任務(wù)的目的。并行Dispatch Queue:該類隊(duì)列可同時(shí)執(zhí)行多個(gè)任務(wù),但是執(zhí)行任務(wù)的順序依然是遵循先進(jìn)先出的原則,同樣可依任務(wù)的不同而在不同的線程中執(zhí)行,這類隊(duì)列通常作為全局隊(duì)列使用。主Dispatch Queue:該類隊(duì)列實(shí)質(zhì)上也是一個(gè)串行隊(duì)列,但是該隊(duì)列是一個(gè)全局隊(duì)列,在該隊(duì)列中執(zhí)行的任務(wù)都是在當(dāng)前應(yīng)用的主線程中執(zhí)行的。通常情況下我們不需要自己創(chuàng)建此類隊(duì)列。
  Dispatch Queue與Operation Queue相似,都能讓我們更方便的實(shí)現(xiàn)并發(fā)任務(wù)的編程工作,并且能提供更優(yōu)的性能,因?yàn)槲覀儾辉傩枰帉戧P(guān)于線程管理相關(guān)的一大堆代碼,這些完全都有系統(tǒng)接管,我們只需要將注意力放在要執(zhí)行的任務(wù)即可。舉個(gè)簡(jiǎn)單的例子,如果有兩個(gè)任務(wù)需要在不同的線程中執(zhí)行,但是他們之間存在資源競(jìng)爭(zhēng)的情況,所以需要保證執(zhí)行的先后順序,如果我們自己創(chuàng)建線程實(shí)現(xiàn)該場(chǎng)景,那么就務(wù)必要用的線程鎖機(jī)制,確保任務(wù)有正確的執(zhí)行順序,這勢(shì)必對(duì)系統(tǒng)資源的開銷會(huì)非常大,如果使用Dispatch Queue,我們只需要將任務(wù)安正確的順序添加到串行隊(duì)列中即可,省時(shí)省力省資源。
  任務(wù)的載體是閉包
  在使用Dispatch Queue時(shí),需要將任務(wù)封裝為閉包。閉包就是一個(gè)函數(shù),或者一個(gè)指向函數(shù)的指針,加上這個(gè)函數(shù)執(zhí)行的非局部變量,閉包最大的一個(gè)特性就是可以訪問父作用域中的局部變量。我們?cè)趯⑷蝿?wù)封裝為閉包進(jìn)行使用時(shí)要注意以下這幾點(diǎn):
  雖然在閉包中可以使用父作用域中的變量,但是盡可能少的使用父作用域中比較大的變量以及不要在閉包中做類似刪除清空父作用域中變量的行為。當(dāng)將一個(gè)封裝好任務(wù)的閉包添加至Dispatch Qeueu中,Dispatch Queue會(huì)自動(dòng)復(fù)制該閉包,并且在執(zhí)行完成后釋放該閉包,所以不同擔(dān)心閉包中一些值的變化問題,以及資源釋放問題。雖然使用Dispatch Queue執(zhí)行并發(fā)異步任務(wù)很方便,但是創(chuàng)建和執(zhí)行閉包還是有一定資源開銷的,所以盡量不要使用Dispatch Queue執(zhí)行一些很小的任務(wù),要物有所值。如果確實(shí)有很小的任務(wù)需要并發(fā)異步執(zhí)行,那么使用NSThread的detachNewThreadSelector方法或NSObject的performSelectorInBackground方法去執(zhí)行也未必不可。如果同一個(gè)隊(duì)列中的多個(gè)任務(wù)之間需要共享數(shù)據(jù),那么應(yīng)該使用隊(duì)列上下文去存儲(chǔ)數(shù)據(jù),供不同的任務(wù)訪問。如果閉包中的任務(wù)創(chuàng)建了不少對(duì)象,那么應(yīng)該考慮將整個(gè)任務(wù)邏輯代碼放在autoreleasepool中,雖然Dispatch Queue中也有自動(dòng)釋放池,但是你不能保證它每次釋放的時(shí)間,所以咱們自己再加一個(gè)要來的更保險(xiǎn)一些。
  創(chuàng)建與管理Dispatch Queues
  在使用Dispatch Queue之前,我們首先需要考慮應(yīng)該創(chuàng)建什么類型的Dispatch Queue,如何進(jìn)行配置等,這一節(jié)就來說一說如何創(chuàng)建和管理Dispatch Queue。
  全局并發(fā)Dispatch Queue
  并發(fā)隊(duì)列的好處人人皆知,可以方便的同時(shí)處理多個(gè)任務(wù),在GCD中并發(fā)Dispatch Queue同樣遵循先進(jìn)先出的原則,但這只是在運(yùn)行時(shí)適用,如果有個(gè)任務(wù)在并發(fā)隊(duì)列中還沒輪到它執(zhí)行,那么此時(shí)完全可以移除它,而不必等它前面的任務(wù)執(zhí)行完成之后。至于并發(fā)隊(duì)列中沒次有多少個(gè)任務(wù)在執(zhí)行,這個(gè)恐怖在每一秒都在變化,因?yàn)橛绊懰囊蛩赜泻芏啵灾罢f過,盡量不要移除移除已經(jīng)添加進(jìn)隊(duì)列的任務(wù)。
  OS X和iOS系統(tǒng)為我們提供了四種全局并發(fā)Dispatch Queue,所謂全局隊(duì)列,就是我們不需要理會(huì)它們的保留和釋放問題,而且不需要專門創(chuàng)建它。與其說是四種不如說是一種全局并發(fā)隊(duì)列的四種不同優(yōu)先級(jí),因?yàn)樗鼈冎g唯一的不同之處就是隊(duì)列優(yōu)先級(jí)不同。與Operation Queue不同,在GCD中,Dispatch Queue只有四種優(yōu)先級(jí):
  DISPATCH_QUEUE_PRIORITY_HIGH:高優(yōu)先級(jí)。DISPATCH_QUEUE_PRIORITY_DEFAULT:默認(rèn)優(yōu)先級(jí),低于高優(yōu)先級(jí)。DISPATCH_QUEUE_PRIORITY_LOW:低優(yōu)先級(jí),低于高優(yōu)先級(jí)和默認(rèn)優(yōu)先級(jí)。DISPATCH_QUEUE_PRIORITY_BACKGROUND:后臺(tái)優(yōu)先級(jí),低于高優(yōu)先級(jí)和后臺(tái)線程執(zhí)行的任務(wù)。
  我們可以通過dispatch_get_global_queue函數(shù)再根據(jù)不同的優(yōu)先級(jí)獲取不同的全局并發(fā)隊(duì)列,類型為dispatch_queue_t:
  lethighPriorityQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0) letdefaultPriorityQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
  我們?cè)谑褂萌植l(fā)隊(duì)列的時(shí)候不需要保留隊(duì)列的引用,隨時(shí)要用隨時(shí)用該函數(shù)獲取即可。當(dāng)然我們也可以通過dispatch_queue_create函數(shù)自己創(chuàng)建隊(duì)列:
  letconcurrentQueue = dispatch_queue_create(“com.example.MyConcurrentQueue”, DISPATCH_QUEUE_CONCURRENT)
  從上面代碼可以看到,dispatch_queue_create函數(shù)有兩個(gè)參數(shù),第一個(gè)為隊(duì)列的名稱,第二個(gè)為隊(duì)列類型,串行隊(duì)列為DISPATCH_QUEUE_SERIAL,并發(fā)隊(duì)列為DISPATCH_QUEUE_CONCURRENT。
  串行Dispatch Queue
  串行隊(duì)列可以讓我們將任務(wù)按照一定順序執(zhí)行,能更優(yōu)的處理多個(gè)任務(wù)之間的資源競(jìng)爭(zhēng)問題,比線程鎖機(jī)制有更小的資源開銷和更好的性能,并且不會(huì)產(chǎn)生死鎖的問題。
  系統(tǒng)也為我們提供了一個(gè)串行隊(duì)列,我們可以通過dispatch_get_main_queue函數(shù)獲?。?br />   letmainQueue = dispatch_get_main_queue()
  該隊(duì)列與當(dāng)前應(yīng)用的主線程相關(guān)聯(lián)。當(dāng)然我們也可以自己創(chuàng)建串行隊(duì)列:
  letserialQueueA = dispatch_queue_create(“com.example.MySerialQueueA”, DISPATCH_QUEUE_SERIAL) // 或者letserialQueueB = dispatch_queue_create(“com.example.MySerialQueueB”, nil)
  dispatch_queue_create函數(shù)的第二個(gè)參數(shù)如果為nil則默認(rèn)創(chuàng)建串行隊(duì)列。當(dāng)我們創(chuàng)建好串行隊(duì)列后,系統(tǒng)會(huì)自動(dòng)將創(chuàng)建好的隊(duì)列與當(dāng)前應(yīng)用的主線程進(jìn)行關(guān)聯(lián)。
  獲取當(dāng)前隊(duì)列
  如果需要驗(yàn)證或者測(cè)試當(dāng)前隊(duì)列,我們可以通過dispatch_get_current_queue函數(shù)獲取當(dāng)前隊(duì)列。如果在閉包中調(diào)用,返回的是該閉包所在的隊(duì)列,如果在閉包外調(diào)用,返回的則是默認(rèn)的并發(fā)隊(duì)列。不過該函數(shù)在OS X v10.10中和Swift中都不能使用了,取而代之的是通過DISPATCH_CURRENT_QUEUE_LABEL屬性的get方法。
  擅用隊(duì)列上下文
  很多情況下,同一個(gè)隊(duì)列中的不同任務(wù)之間需要共享數(shù)據(jù),尤其像串行隊(duì)列中的任務(wù),可能由多個(gè)任務(wù)對(duì)某個(gè)變量進(jìn)行處理,或者都需要使用到某個(gè)對(duì)象,這時(shí)就要用到隊(duì)列上下文:
  import Foundation classTestDispatchQueue{func launch() { let serialQueue = dispatch_queue_create(“com.example.MySerialQueue”, DISPATCH_QUEUE_SERIAL) dispatch_set_context(serialQueue, unsafeBitCast(0, UnsafeMutablePointer《Int》.self)) dispatch_async(serialQueue, { vartaskCount = unsafeBitCast(dispatch_get_context(serialQueue), Int.self) taskCount++ print(“TaskA in the dispatch queue.。.and The number of task in queue is \(taskCount)”) dispatch_set_context(serialQueue, unsafeBitCast(taskCount, UnsafeMutablePointer《Int》.self)) sleep(1) }) dispatch_async(serialQueue, { vartaskCount = unsafeBitCast(dispatch_get_context(serialQueue), Int.self) taskCount++ print(“TaskB in the dispatch queue.。.and The number of task in queue is \(taskCount)”) dispatch_set_context(serialQueue, unsafeBitCast(taskCount, UnsafeMutablePointer《Int》.self)) }) sleep(3) } } let testDispatchQueue = TestDispatchQueue() testDispatchQueue.launch()
  從上面的代碼示例中可以看到,在執(zhí)行代碼點(diǎn),我們用dispatch_set_context函數(shù)向serialQueue隊(duì)列的上下文環(huán)境中設(shè)置了一個(gè)Int類型的變量,初始值為0。該函數(shù)有兩個(gè)參數(shù),第一個(gè)是目標(biāo)隊(duì)列,第二個(gè)參數(shù)是上下文數(shù)據(jù)的指針。然后在閉包中我們使用dispatch_get_context函數(shù)獲取上下文數(shù)據(jù)進(jìn)行進(jìn)一步的處理。除了基本類型,我們也可以將自定義的類放入隊(duì)列上下文中:
  importFoundation class Contact: NSObject { letname =“DevTalking”letmobile =“10010”} class TestDispatchQueue { letcontact =Contact() func launch() { letserialQueue =dispatch_queue_create(“com.example.MySerialQueue”, DISPATCH_QUEUE_SERIAL) dispatch_set_context(serialQueue, unsafeBitCast(contact, UnsafeMutablePointer《Void》.self)) dispatch_async(serialQueue, { letcontact =unsafeBitCast(dispatch_get_context(serialQueue), Contact.self) print(“The name is \(contact.name)”) sleep(1) }) dispatch_async(serialQueue, { letcontact =unsafeBitCast(dispatch_get_context(serialQueue), Contact.self) print(“The name is \(contact.mobile)”) }) sleep(3) } } lettestDispatchQueue =TestDispatchQueue() testDispatchQueue.launch()
  關(guān)于unsafeBitCast函數(shù)和Swift中指針的用法在這里可以有所參考。
  隊(duì)列的收尾工作
  雖然在ARC時(shí)代,資源釋放的工作已經(jīng)基本不需要我們手動(dòng)去做了,但有些時(shí)候因?yàn)橄到y(tǒng)釋放資源并不是很及時(shí),也會(huì)造成內(nèi)存移除等問題,所以在一些情況下我們還是需要進(jìn)行手動(dòng)釋放資源的工作,必入添加autoreleasepool保證資源及時(shí)釋放等。Dispatch Queue也給我們提供了這樣的機(jī)會(huì)(機(jī)會(huì)針對(duì)于ARC時(shí)代,在MRC時(shí)代是必須要做的),那就是Clean Up Function清理掃尾函數(shù),當(dāng)隊(duì)列被釋放時(shí),或者說引用計(jì)數(shù)為0時(shí)會(huì)調(diào)用該函數(shù),并且將上下文指針也傳到了該函數(shù),以便進(jìn)行清理工作:
  importFoundation class Contact: NSObject { letname =“DevTalking”letmobile =“10010”} class TestDispatchQueue { letcontact =Contact() func testCleanUpFunction() { launch() sleep(15) } func launch() { letserialQueue =dispatch_queue_create(“com.example.MySerialQueue”, DISPATCH_QUEUE_SERIAL) dispatch_set_context(serialQueue, unsafeBitCast(contact, UnsafeMutablePointer《Void》.self)) dispatch_set_finalizer_f(serialQueue, myFinalizerFunction()) dispatch_async(serialQueue, { letcontact =unsafeBitCast(dispatch_get_context(serialQueue), Contact.self) print(“The name is \(contact.name)”) sleep(1) }) dispatch_async(serialQueue, { letcontact =unsafeBitCast(dispatch_get_context(serialQueue), Contact.self) print(“The name is \(contact.mobile)”) }) sleep(3) } func myFinalizerFunction() -》 dispatch_function_t { return{ context inletcontact =unsafeBitCast(context, Contact.self) print(“The name is \(contact.name) and the mobile is \(contact.mobile), The serialQueue has been released and we need clean up context data.”) // TODO.。. } } } lettestDispatchQueue =TestDispatchQueue() testDispatchQueue.testCleanUpFunction()
  從上面的代碼示例中可以看到當(dāng)給隊(duì)列設(shè)置完上下文時(shí),我們使用了dispatch_set_finalizer_f函數(shù)給隊(duì)列設(shè)置清理函數(shù),dispatch_set_finalizer_f函數(shù)有兩個(gè)參數(shù),第一個(gè)是目標(biāo)隊(duì)列,第二個(gè)參數(shù)是類型為dispatch_function_t的函數(shù)指針,也就是清理函數(shù),上下文數(shù)據(jù)指針是該函數(shù)唯一的參數(shù)。在上面代碼中,我們添加了myFinalizerFunction函數(shù)作為清理函數(shù),在該函數(shù)中獲得上下文數(shù)據(jù),然后進(jìn)行后續(xù)的清理工作。
?

非常好我支持^.^

(0) 0%

不好我反對(duì)

(0) 0%

      發(fā)表評(píng)論

      用戶評(píng)論
      評(píng)價(jià):好評(píng)中評(píng)差評(píng)

      發(fā)表評(píng)論,獲取積分! 請(qǐng)遵守相關(guān)規(guī)定!

      ?