




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、畢業(yè)論文題 目:ios平臺(tái)下并發(fā)編程的研究和實(shí)現(xiàn)姓 名: 學(xué) 號(hào):指導(dǎo)教師(職稱): 專 業(yè): 班 級(jí):所 在 學(xué) 院: 2015年6月武漢工程大學(xué) 畢業(yè)論文目 錄摘 要 iiiabstract . v第一章 緒 論 11.1 移動(dòng)開發(fā)中的并發(fā)編程 . 11.2 移動(dòng)操作系統(tǒng)ios的發(fā)展 . 11.3 論文章節(jié)安排 . 2第二章 并發(fā)程序的設(shè)計(jì) .32.1 摒棄線程 . 32.2 異步編程技術(shù)介紹 . 42.3 異步編程設(shè)計(jì) . 52.4 衡量引入并發(fā)后對(duì)程序性能的影響 . 62.5 何時(shí)使用原生線程 . 6第三章 操作隊(duì)列73.1 nsoperation 對(duì)象簡(jiǎn)介 . 73.2 子類化 ns
2、operation . 73.3 自定義操作對(duì)象的執(zhí)行行為 .113.4 開始執(zhí)行操作對(duì)象 .12第四章 調(diào)度隊(duì)列. 154.1 調(diào)度隊(duì)列介紹 .154.2 與隊(duì)列相關(guān)的一些技術(shù)點(diǎn) .164.3 使用block實(shí)現(xiàn)任務(wù) .164.4 創(chuàng)建和管理調(diào)度隊(duì)列 .174.5 添加任務(wù)到隊(duì)列中 .204.6 掛起和恢復(fù)調(diào)度隊(duì)列 .224.7 使用dispatch信號(hào)量控制可用的有限資源.234.8 等待一組任務(wù)的完成 .234.9 調(diào)度隊(duì)列和線程安全 .24第五章 調(diào)度源. 255.1 dispatch source介紹 . 255.2 創(chuàng)建dispatch source . 265.3 使用調(diào)度源的一
3、些例子 .29總 結(jié) .35致 謝 .37參考文獻(xiàn) .39- 40 -摘 要 移動(dòng)互聯(lián)網(wǎng)的浪潮席卷而至,隨著智能手機(jī)等設(shè)備上中央處理器性能的提升,以及多核cpu在移動(dòng)終端上的普及,每個(gè)處理器上的核心只會(huì)增加。這種設(shè)備性能上的提升使得其應(yīng)用程序?qū)?huì)更加快捷流暢,程序更加高效以及產(chǎn)品更好的用戶體驗(yàn)。在計(jì)算機(jī)中,單個(gè)核心下的并發(fā)一般為時(shí)間片的輪流,宏觀上為多個(gè)任務(wù)同時(shí)執(zhí)行,微觀上每個(gè)時(shí)刻仍然只執(zhí)行一個(gè)任務(wù)。由于多核時(shí)代的來臨,線程才開始擁有了真正意義上的并行處理。多線程也作為越來越重要的一個(gè)部分需要開發(fā)者來掌握。然而受限于設(shè)備能耗以及內(nèi)存大小等問題,移動(dòng)應(yīng)用開發(fā)中的多線程編程又區(qū)別于其他程序開發(fā)。作
4、為開發(fā)者,需要擁抱變化,積極的適應(yīng)技術(shù)的發(fā)展,并提升自己。關(guān)鍵詞:并發(fā)編程;移動(dòng)互聯(lián)網(wǎng);多線程;移動(dòng)應(yīng)用開發(fā)abstractwith the advent of mobile internet, cpu performance boost on smartphones and other devices, multi-core cpu on mobile devices became common, the cores of processor will more and more. this performance upgrades of device that make the appli
5、cation will be faster and more smooth, procedures more efficient, and it will have a better user experience. on the computer, concurrent of single core is time turns. looks at the macro level is performed multiple tasks at the same time, micro level each time still perform only one task. because of
6、the advent of the multi-core processor, the thread began with a real sense of concurrent processing. development of multithread increasing importance, and requires the developer to learn. however, due to the limitations of devices energy consumption and memory size, concurrent programming in mobile
7、application development is different from other programming. as a developer, you need to embrace change, learn the latest techniques, and improve yourself.keywords:concurrency programming;mobile internet;multithreading;mobile application development第一章 緒 論在移動(dòng)應(yīng)用開發(fā)中,由于受限與設(shè)備屏幕尺寸、處理器性能以及能耗等問題,與傳統(tǒng)軟件開發(fā)有不同
8、之處。從提升程序性能開始,著重介紹如何利用多核處理器進(jìn)行ios平臺(tái)下的多線程開發(fā)。1.1移動(dòng)開發(fā)中的并發(fā)編程并發(fā)所描述的概念就是同時(shí)運(yùn)行多個(gè)任務(wù)。這些任務(wù)在單核 cpu 上所采取的方案為時(shí)間片輪流,即同一時(shí)間段內(nèi)執(zhí)行多核任務(wù),但是同一時(shí)刻只有一個(gè)任務(wù)處于執(zhí)行狀態(tài)。在多核 cpu 上才以真正的并行方式來運(yùn)行。現(xiàn)在大多數(shù)智能設(shè)備處理器都至少有兩個(gè)核心,移動(dòng)操作系統(tǒng)能夠并行的運(yùn)行多個(gè)程序,其中大多數(shù)的程序運(yùn)行在后臺(tái),并且經(jīng)常需要一小段 cpu 時(shí)間來執(zhí)行任務(wù)。運(yùn)行在前臺(tái)的程序與用戶交互并且占用大量的 cpu 時(shí)間。如果一個(gè)程序需要很多任務(wù)去執(zhí)行,但是只能使用處理器中的一部分核心,那么多核的特性將無法
9、發(fā)揮,額外的計(jì)算資源將被浪費(fèi)。因此,程序需要充分利用處理器的多核特性,將處理器的性能充分挖掘出來,提高程序的性能以及用戶體驗(yàn)。隨著移動(dòng)開發(fā)領(lǐng)域的快速發(fā)展,對(duì)于開發(fā)者,需要擁抱變化,盡快掌握移動(dòng)端的多線程編程技術(shù)。1.2移動(dòng)操作系統(tǒng)ios的發(fā)展在國(guó)內(nèi)外,ios 系統(tǒng)擁有眾多開發(fā)者的支持,2014年3月份,appstore 中的應(yīng)用數(shù)已經(jīng)超過100萬,國(guó)內(nèi)和國(guó)外開始進(jìn)入ios開發(fā)領(lǐng)域的技術(shù)人員也再高速增長(zhǎng)。os x 和 ios 提供了幾種不同的 api 來支持并發(fā)編程。每一條 api 都具有不同的功能和使用上的一些限制,這就需要在不同的情景下使用最適合的并發(fā)方式。同時(shí),這些 api 本身處在不同的
10、抽象層級(jí)上。我們很可能會(huì)使用它們進(jìn)行一些特別底層的操作,但同時(shí)也意味著將背負(fù)起處理好這些操作的責(zé)任。為了利用多核,計(jì)算機(jī)需要軟件能夠同時(shí)干多件事情?,F(xiàn)代的多任務(wù)操作系統(tǒng),可以有上百的程序在給定的時(shí)間內(nèi)運(yùn)行,所以可以調(diào)度每個(gè)程序執(zhí)行在不同的核上。然而,大多數(shù)的程序?qū)儆谙到y(tǒng)駐守進(jìn)程,或那些運(yùn)行在后臺(tái),只需要很少 cpu 時(shí)間的程序。相反,真正的需要是為單個(gè)應(yīng)用程序高效地使用處理器額外的核心。應(yīng)用程序利用多核的傳統(tǒng)方式是創(chuàng)建多個(gè)線程,然而,由于核心的增加,有許多線程相關(guān)的問題需要解決,最大的問題是線程代碼不能很好的拓展到任意數(shù)目的核心。不能創(chuàng)建很多的線程,然后認(rèn)為程序會(huì)很好的運(yùn)行這些線程。我們無法確
11、認(rèn)具體使用多少個(gè)核心才是最高效的,程序本身也無法很好地通過計(jì)算得出這個(gè)數(shù)值。即使得到了正確的數(shù)字,想要這么多線程之間不能干擾且高效運(yùn)行,仍然具有很大的難度。所以我們需要一種抽象層次比線程高,同時(shí)效率又不能比線程太低的方式來處理并發(fā)。1.3論文章節(jié)安排在過去,在程序中引入并發(fā)需要?jiǎng)?chuàng)建額外的一個(gè)或多個(gè)線程。不幸的是,寫線程級(jí)別的代碼很具有挑戰(zhàn)性。線程是很底層的工具,必須手動(dòng)來管理。對(duì)于一個(gè)程序,由于線程的最佳數(shù)目基于系統(tǒng)負(fù)載和底層硬件而動(dòng)態(tài)改變,因此實(shí)現(xiàn)一個(gè)正確的線程解決方案是非常困難和復(fù)雜的。此外,線程的同步機(jī)制通常會(huì)給軟件設(shè)計(jì)增加復(fù)雜性和帶來風(fēng)險(xiǎn),有時(shí)候并不能保證一定會(huì)提高程序性能。相比較傳統(tǒng)
12、的基于線程的系統(tǒng)和應(yīng)用程序,os x 和 ios 更多地采用異步方法來執(zhí)行并行任務(wù)。應(yīng)用程序只需要定義特定的任務(wù),然后讓系統(tǒng)執(zhí)行它們,而不是直接創(chuàng)建線程。通過讓操作系統(tǒng)來管理線程,使得應(yīng)用程序具有了原生線程不可能具有的可擴(kuò)展性,同時(shí)開發(fā)者也有了更加簡(jiǎn)單高效的編程模式。論文主要介紹了ios平臺(tái)下并發(fā)編程的技術(shù)和技巧,包含以下章節(jié):1. 并行和程序設(shè)計(jì):介紹了基本的異步程序設(shè)計(jì)和異步執(zhí)行自定義任務(wù)的技巧。2. operation queues(操作隊(duì)列):介紹如何使用 objective-c 對(duì)象封裝任務(wù)并且執(zhí)行。3. dispatch queue(調(diào)度隊(duì)列):在 c 語言編程環(huán)境中,如何并行地執(zhí)
13、行任務(wù)。4. dispatch sources:如何異步的處理系統(tǒng)事件。第二章 并發(fā)程序的設(shè)計(jì)早期的計(jì)算機(jī)執(zhí)行最小任務(wù)所需的時(shí)間單元取決于cpu的時(shí)鐘速度,但隨著cpu技術(shù)的發(fā)展以及處理器上的核心越來越密集,散熱和其他物理因素開始影響cpu的最大時(shí)鐘速度。因此廠商們開始將注意力轉(zhuǎn)移到如何在單個(gè)芯片上加入更多的處理器核心,即多核cpu,這樣單個(gè)芯片的性能將又得到提升,因而剩下的問題就是如何充分利用這些增加的核心。傳統(tǒng)意義上利用cpu多核特性的方式為創(chuàng)建多個(gè)線程,然而移動(dòng)設(shè)備上的cpu受限于系統(tǒng)負(fù)載和散熱等其他因素,不可以創(chuàng)建大量的線程而又使得程序很好的運(yùn)行。因此需要一種比較好的方式來解決移動(dòng)端多
14、線程編程的問題。2.1摒棄線程線程是利用處理器多核特性最直接的方式,也是組成進(jìn)程的子單元,操作系統(tǒng)的調(diào)度器可以對(duì)線程進(jìn)行單獨(dú)的調(diào)度。但是線程無法解決如何彈性地執(zhí)行多個(gè)任務(wù)這個(gè)很普遍的問題,我們無法控制自己線程中的代碼在什么時(shí)候開始執(zhí)行,需要執(zhí)行多長(zhǎng)時(shí)間,什么時(shí)候暫停。直接使用線程執(zhí)行任務(wù)的另一個(gè)問題是,如果線程中的代碼使用了框架或庫時(shí),那么執(zhí)行任務(wù)所增加的線程總數(shù)有可能以指數(shù)級(jí)別增長(zhǎng)。例如,在8核cpu中,創(chuàng)建8個(gè)線程完成某個(gè)任務(wù),看起來似乎充分利用了cpu的多個(gè)核心,但是很有可能每個(gè)線程中用到的某個(gè)框架又創(chuàng)建了多個(gè)線程1。創(chuàng)建每個(gè)線程都會(huì)消耗一些內(nèi)存和內(nèi)核資源,因此如何動(dòng)態(tài)地拓展線程數(shù)目就變
15、得尤為重要,我們期望根據(jù)系統(tǒng)負(fù)載和當(dāng)前可用的資源能夠動(dòng)態(tài)的控制當(dāng)前活動(dòng)線程的數(shù)量。如果把這項(xiàng)任務(wù)交由開發(fā)者,那么多線程編程將會(huì)變得更加復(fù)雜,因此,最好的方式是使用系統(tǒng)為我們提供的并發(fā)編程模型。為了不依賴于線程,ios中采用異步編程的方式來處理需要后臺(tái)運(yùn)行的任務(wù)。異步這個(gè)概念已經(jīng)存在于計(jì)算機(jī)中很長(zhǎng)時(shí)間了,主要用于執(zhí)行一些需要花費(fèi)很長(zhǎng)時(shí)間的任務(wù),例如從磁盤中讀取文件,從網(wǎng)絡(luò)上獲取數(shù)據(jù)等。當(dāng)異步函數(shù)被調(diào)用后,任務(wù)就會(huì)在后臺(tái)開始執(zhí)行,同時(shí)函數(shù)會(huì)立刻返回,同時(shí)繼續(xù)執(zhí)行后續(xù)的任務(wù)。當(dāng)處于后臺(tái)中的任務(wù)執(zhí)行完成后,會(huì)發(fā)送通知給調(diào)用者(通常為函數(shù)回調(diào)),調(diào)用者在函數(shù)回調(diào)中處理任務(wù)完成后的相關(guān)操作。這種異步的方式
16、既不影響當(dāng)前任務(wù)的執(zhí)行,又能利用額外的核心完成非常耗時(shí)的操作。在ios平臺(tái)下,apple已經(jīng)提供了幾種異步的編程技術(shù),下面主要介紹這些技術(shù)。使用異步編程的技術(shù)之一為 gcd(grand central dispatch)。這項(xiàng)技術(shù)能夠?qū)⒃鹃_發(fā)者需要編寫的線程管理代碼轉(zhuǎn)移到系統(tǒng)級(jí)別,開發(fā)者只需定義需要執(zhí)行的任務(wù)并將其添加到適合的調(diào)度隊(duì)列即可。gcd 負(fù)責(zé)創(chuàng)建線程并在線程上執(zhí)行任務(wù)所需的代碼,現(xiàn)在由于線程管理是系統(tǒng)的一部分,gcd接管了線程管理以及任務(wù)的執(zhí)行,因此這種方式要比傳統(tǒng)創(chuàng)建線程的方式高效一些,更重要的是極大地減輕了開發(fā)者的負(fù)擔(dān)。另一種使用異步編程的技術(shù)為 operation queue
17、,它是 objective-c 對(duì)象,如同調(diào)度隊(duì)列一樣,開發(fā)者只需定義需要執(zhí)行的任務(wù)然后將其添加到操作隊(duì)列中,操作隊(duì)列將負(fù)責(zé)任務(wù)的調(diào)度和執(zhí)行。跟 gcd 一樣,操作隊(duì)列處理所有線程管理的工作,并且高效地執(zhí)行任務(wù)代碼。2.2異步編程技術(shù)介紹下面主要介紹ios平臺(tái)中異步編程的幾種技術(shù)。2.2.1調(diào)度隊(duì)列dispatch queue調(diào)度隊(duì)列是一種基于c語言的自定義任務(wù)執(zhí)行機(jī)制。調(diào)度隊(duì)列串行或并行地執(zhí)行任務(wù),任務(wù)開始執(zhí)行的順序與其添加順序一致。串行的調(diào)度隊(duì)列同一時(shí)間只能執(zhí)行單個(gè)任務(wù),需要等待上個(gè)任務(wù)完成后才可以開始下個(gè)任務(wù)的執(zhí)行。并行的調(diào)度隊(duì)列在同一時(shí)間內(nèi)可以執(zhí)行多個(gè)任務(wù),并不需要等待上個(gè)任務(wù)完成。調(diào)
18、度隊(duì)列具有以下優(yōu)點(diǎn):1. 簡(jiǎn)潔明了的編程接口。2. 自動(dòng)全面的線程池管理方案。3. 可提供調(diào)度組件的速度。4. 更好的內(nèi)存利用率(因?yàn)榫€程棧不處于應(yīng)用程序本身內(nèi)存區(qū))。5. 任務(wù)的異步調(diào)用不會(huì)導(dǎo)致死鎖。6. 競(jìng)爭(zhēng)條件下?lián)碛懈线m的粒度。7. 串行隊(duì)列提供了更加有效的同步機(jī)制。提交到調(diào)度隊(duì)列中的任務(wù)必須封裝為block對(duì)象或者是一個(gè)函數(shù),調(diào)度隊(duì)列是gcdgcd和c運(yùn)行時(shí)的一部分。2.2.2調(diào)度源dispatch sources調(diào)度源是用于異步處理特殊系統(tǒng)類型事件的基于c語言的機(jī)制。一個(gè)調(diào)度源封裝特殊系統(tǒng)類型事件的相關(guān)信息,當(dāng)發(fā)生該事件時(shí),向調(diào)度隊(duì)列提交函數(shù)或特殊的block對(duì)象。簡(jiǎn)單來說,調(diào)度源
19、是一個(gè)監(jiān)視某些類型事件的對(duì)象。當(dāng)這些事件發(fā)生時(shí),它自動(dòng)將一個(gè)block對(duì)象放入一個(gè)調(diào)度隊(duì)列的執(zhí)行例程中。可以使用調(diào)度源來監(jiān)聽以下系統(tǒng)事件:計(jì)時(shí)器、信號(hào)處理描述符相關(guān)的進(jìn)程事件、mach 端口事件和自定義的觸發(fā)事件2。2.2.3操作隊(duì)列operation queues操作隊(duì)列由ios中nsoperationqueue類實(shí)現(xiàn)。相比較調(diào)度隊(duì)列按照添加順序執(zhí)行任務(wù),操作隊(duì)列在決定任務(wù)執(zhí)行順序時(shí)還會(huì)考慮其他一系列因素。提交到操作隊(duì)列的對(duì)象必須是nsoperation類的子類,nsoperation子類的對(duì)象封裝執(zhí)行的任務(wù)以及所需的數(shù)據(jù)。2.3異步編程設(shè)計(jì)在考慮將現(xiàn)有的代碼重新設(shè)計(jì)以支持并發(fā)時(shí),首先應(yīng)該確
20、認(rèn)是否有這個(gè)必要。一般來說,并發(fā)將大多數(shù)耗時(shí)任務(wù)放至其他工作線程執(zhí)行,可以使得主線程空閑。由于ios中有關(guān)ui部分的事件都在主線程中處理,因此空閑的主線程能夠更加有效地處理相應(yīng)用戶事件,使得界面更加流暢,提升用戶體驗(yàn),同時(shí)還能利用多核特性做更多的工作。當(dāng)然,引入并發(fā)也會(huì)增加開銷和代碼量,增加編碼和debug難度。由于增加了軟件設(shè)計(jì)的復(fù)雜性,并發(fā)并不是產(chǎn)品開發(fā)周期快結(jié)束時(shí)需要加入的一個(gè)功能點(diǎn)。每一個(gè)程序都有不同的需求和指導(dǎo)任務(wù),可以大概通過以下幾點(diǎn)來確認(rèn)是否應(yīng)該引入并發(fā)。2.3.1明確應(yīng)用程序預(yù)期的行為在考慮程序中引入并發(fā)前,首先應(yīng)該從明確程序正確的行為開始。了解程序預(yù)期的行為,在之后的設(shè)計(jì)中可
21、以幫助驗(yàn)證設(shè)計(jì)的可行性。第一件事,就是羅列出程序所有要做的任務(wù)以及相關(guān)的數(shù)據(jù)結(jié)構(gòu)。一開始,可能會(huì)從用戶的點(diǎn)擊事件任務(wù)開始,因?yàn)橛脩酎c(diǎn)擊事件提供了很清晰的需求,用戶點(diǎn)擊了哪里,期望得到什么樣的行為。實(shí)際中更應(yīng)該羅列其他無需用戶交互的應(yīng)用程序任務(wù),比如基于計(jì)時(shí)器的任務(wù)。當(dāng)整理出較高級(jí)別任務(wù)的列表后,將任務(wù)再分解為完成所需的一系列步驟,在這個(gè)階段,應(yīng)該是主要是對(duì)數(shù)據(jù)或者對(duì)象做一些修改,以及了解這些修改如何影響程序的整體狀態(tài)。還應(yīng)該注意對(duì)象和數(shù)據(jù)結(jié)構(gòu)之間的依賴關(guān)系,注意對(duì)一個(gè)對(duì)象的修改是否影響其他對(duì)象。2.3.2分解出任務(wù)的執(zhí)行單元在羅列程序任務(wù)時(shí),應(yīng)該基本明確哪些任務(wù)并發(fā)處理時(shí)會(huì)高效一些。如果整個(gè)任
22、務(wù)中更改了某些步驟的執(zhí)行順序,任務(wù)執(zhí)行結(jié)果會(huì)改變,那么可能需要考慮串行執(zhí)行這些步驟。如果任務(wù)的執(zhí)行結(jié)果與任務(wù)中步驟的執(zhí)行順序無關(guān),那么可以使用并發(fā)來提高性能。這種情況下,將任務(wù)拆分出一步一步執(zhí)行的單元,然后將它們封裝成block或者operation對(duì)象并分發(fā)到對(duì)應(yīng)的隊(duì)列。在確定任務(wù)中的每個(gè)執(zhí)行單元時(shí),一開始不需要過多的擔(dān)心工作量是不是太大。即使開啟線程需要一定的開銷,但是調(diào)度隊(duì)列和操作隊(duì)列的一個(gè)優(yōu)點(diǎn)就是在多數(shù)情況下仍比傳統(tǒng)使用線程的方式開銷要小的多。所以,在使用隊(duì)列執(zhí)行一些很小的工作單元時(shí),效率是高于使用線程的。當(dāng)然,仍需要通過衡量實(shí)際運(yùn)行時(shí)的效率來調(diào)整任務(wù)的大小,但是在一開始,沒必要考慮任
23、務(wù)單元是不是拆分得太小了。2.3.3決定需要分發(fā)任務(wù)的隊(duì)列現(xiàn)在已經(jīng)將任務(wù)拆分為工作單元,并且用block或者nsoperation對(duì)象封裝起來了。如果使用block封裝任務(wù),可以向一個(gè)串行或并行的隊(duì)列添加block來執(zhí)行。如果對(duì)于執(zhí)行順序有特殊的要求,應(yīng)該使用串行的隊(duì)列。如果工作單元對(duì)于執(zhí)行順序沒有要求,可以使用并發(fā)的隊(duì)列或者多個(gè)不同的并發(fā)隊(duì)列,具體取決于程序需求。如果使用nsoperation對(duì)象,那么配置對(duì)象將比選擇隊(duì)列更加重要。想要串行地執(zhí)行nsoperation對(duì)象,必須要先處理這些對(duì)象之間的依賴關(guān)系。依賴項(xiàng)會(huì)阻止當(dāng)前操作繼續(xù)執(zhí)行,直到所依賴的對(duì)象完成它們的工作。2.4衡量引入并發(fā)后對(duì)
24、程序性能的影響調(diào)度隊(duì)列、操作隊(duì)列和調(diào)度源都提供了簡(jiǎn)單的并發(fā)編程方式。然而這些技術(shù)并不能保證一定能夠提高程序的性能或改善代碼的執(zhí)行效率。因此仍然需要以一種合理的方式去使用并發(fā),且不能過度的使用操作系統(tǒng)資源。在代碼中引用并發(fā)之前,無論是使用隊(duì)列還是線程,都應(yīng)該采集一些基準(zhǔn)的性能指標(biāo)反映當(dāng)前的程序性能。當(dāng)使用并發(fā)后,采集并發(fā)后的性能指標(biāo)與之前的基準(zhǔn)進(jìn)行比較,看并發(fā)的引入是否提高了程序性能,推薦使用性能測(cè)試工具來檢測(cè)。2.5何時(shí)使用原生線程雖然操作隊(duì)列和調(diào)度隊(duì)列是執(zhí)行并發(fā)的首選方式,但這并不是適用于任何情況的。根據(jù)應(yīng)用程序任務(wù)需求的不同,有時(shí)候可能仍需創(chuàng)建自定義的線程。如果的確有這個(gè)需要,那么盡可能使
25、用更少的線程,盡量不要使用線程做其他的操作。線程仍然是實(shí)現(xiàn)代碼運(yùn)行在確定時(shí)間的最佳方式,調(diào)度隊(duì)列盡管會(huì)盡可能快速地執(zhí)行任務(wù),但是仍然不能解決真實(shí)時(shí)間約束。如果需要了解更多線程運(yùn)行在后臺(tái)的預(yù)計(jì)行為,線程通常會(huì)提供更好的選擇。不過,使用線程時(shí)最好再次確認(rèn)其必要性。第三章 操作隊(duì)列在ios平臺(tái)中,cocoa 框架中的 nsoperation 通過面向?qū)ο蟮姆绞椒庋b了執(zhí)行異步操作的工作,主要用于 operation queue。本章節(jié)主要介紹 nsoperation 類的使用以及自定義子類化。3.1nsoperation對(duì)象簡(jiǎn)介operation對(duì)象是nsoperation類的實(shí)例,用來封裝程序中需要
26、異步執(zhí)行的一些操作。nsoperation是抽象基類,所以不能直接使用,需要通過繼承實(shí)現(xiàn)自己的子類來執(zhí)行任務(wù)。由于基類本身已經(jīng)實(shí)現(xiàn)了一些基本操作,所以可以很方便地繼承它。除此之外,cocoa 框架還提供了兩個(gè)已經(jīng)定義好的子類,用于一些常用的異步操作,可以在代碼中直接使用它們3。第一個(gè)子類為nsinvocationoperation,基于一個(gè)方法選擇子和對(duì)象創(chuàng)建的對(duì)象,當(dāng)程序中已經(jīng)存在現(xiàn)有的方法,并且希望異步執(zhí)行時(shí),是一個(gè)較好的選擇。第二個(gè)子類為nsblockoperation,可以使用這個(gè)類并發(fā)地執(zhí)行一個(gè)或多個(gè)block對(duì)象。當(dāng)所有相關(guān)的block執(zhí)行完畢后,operation對(duì)象才完成。當(dāng)上
27、面提供的兩個(gè)類不能滿足需求時(shí),可以考慮定義自己的nsoperation子類。這樣可以獲得更多有關(guān)操作對(duì)象的控制權(quán),通常用于一些比較復(fù)雜的操作。所有的操作對(duì)象都支持以下重要的功能:1.支持操作對(duì)象間建立基于圖論的依賴關(guān)系,這些依賴項(xiàng)會(huì)阻止當(dāng)前對(duì)象的運(yùn)行,直到對(duì)象所依賴的其他項(xiàng)都完成。2.支持一個(gè)可選的completion block,當(dāng)操作對(duì)象的主任務(wù)完成時(shí)調(diào)用。3.支持監(jiān)聽操作對(duì)象狀態(tài)的改變,需要操作對(duì)象使用 kvo。4.支持優(yōu)先級(jí),會(huì)影響操作對(duì)象的執(zhí)行順序。5.支持取消操作對(duì)象的執(zhí)行,正在執(zhí)行時(shí)也可以取消。操作對(duì)象旨在提高程序的并發(fā)性,同時(shí)也是一種很好的封裝應(yīng)用程序行為的方式。應(yīng)該提交操作對(duì)
28、象到操作隊(duì)列上,讓它們?cè)趩为?dú)的線程或者多個(gè)線程上執(zhí)行相應(yīng)的工作,而不是在主線程上做大量的操作。3.2子類化nsoperation nsoperation類為所有的操作對(duì)象提供了一些基本的子類化點(diǎn)。同時(shí)提供了大量的基礎(chǔ)方法用于實(shí)現(xiàn)kvo依賴,然而,有時(shí)候仍需補(bǔ)充現(xiàn)有的基礎(chǔ)結(jié)構(gòu),來確保業(yè)務(wù)的正常運(yùn)行。其他一些額外的工作量取決于是否實(shí)現(xiàn)并發(fā)操作。定義非并發(fā)的操作要比并發(fā)簡(jiǎn)單的多,對(duì)于非并發(fā)的操作,只需要執(zhí)行主要任務(wù)并實(shí)現(xiàn)取消方法。對(duì)于并發(fā)操作,必須重載現(xiàn)有的一些代碼,下面各節(jié)主要講述重載的內(nèi)容。3.2.1執(zhí)行主任務(wù)每個(gè)操作對(duì)象至少需要實(shí)現(xiàn)初始化和主任務(wù)這兩個(gè)方法,通過這兩個(gè)方法,操作對(duì)象可以實(shí)例化并
29、且得到一個(gè)需要執(zhí)行的任務(wù)。代碼示例如下:interface cwnonconcurrentoperation : nsoperationproperty id (strong) data;-(id)initwithdata:(id)data;endimplementation cwnonconcurrentoperation- (id)initwithdata:(id)data if (self = super init) mydata = data; return self;/ 主任務(wù)-(void)main try / 根據(jù)當(dāng)前操作對(duì)象的數(shù)據(jù)進(jìn)行處理,得出結(jié)果 catch(.) / 不要在這
30、里拋出異常 end3.2.2實(shí)現(xiàn)取消操作當(dāng)操作對(duì)象開始執(zhí)行后,只有顯示地取消時(shí),才會(huì)真正結(jié)束執(zhí)行。取消操作可以發(fā)生在任何時(shí)間,甚至在操作對(duì)象還未開始執(zhí)行時(shí)。盡管nsoperation抽象基類已經(jīng)提供了取消操作,但是應(yīng)該在子類中重載它,并在取消操作中釋放已經(jīng)占有的資源。操作對(duì)象應(yīng)該在整個(gè)執(zhí)行周期中檢查是否有取消事件發(fā)生,并且優(yōu)雅地處理該事件。支持取消需要做的就是在代碼中周期性的調(diào)用操作對(duì)象的 iscancelled 方法,并且當(dāng)不返回yes時(shí)立刻返回。支持取消操作是很重要的,iscancelled方法調(diào)用返回非??欤虼丝梢灶l繁的調(diào)用而不會(huì)造成額外的開銷。可能需要在以下地方調(diào)用iscancell
31、ed方法:1. 在執(zhí)行任何自然操作時(shí)立刻調(diào)用。2. 在循環(huán)中至少調(diào)用一次,或者當(dāng)循環(huán)耗時(shí)較長(zhǎng)時(shí)調(diào)用多次。3. 任何可能中斷操作的地方。3.2.3配置操作對(duì)象使其并發(fā)執(zhí)行默認(rèn)情況下操作隊(duì)列以同步方式執(zhí)行,也就是說它們?cè)谡{(diào)用start方法的線程上執(zhí)行任務(wù)。操作隊(duì)列為非并發(fā)的任務(wù)提供了線程,不過現(xiàn)在大多數(shù)操作需要異步運(yùn)行,因此需要重載一些方法。下面列出了并發(fā)執(zhí)行時(shí)需要重載的方法:start :(必須)所有的并發(fā)操作必須重載這個(gè)方法,實(shí)現(xiàn)自定義的行為。通過調(diào)用start方法手動(dòng)執(zhí)行操作。因此,這個(gè)方法的實(shí)現(xiàn)是操作開始執(zhí)行的起點(diǎn),并且是設(shè)置線程或者其他運(yùn)行環(huán)境的地方。需要注意的是任何時(shí)候都不能調(diào)用sup
32、er。main:(可選)這個(gè)方法通常用于實(shí)現(xiàn)操作對(duì)象相應(yīng)的任務(wù)。盡管可以在start方法中實(shí)現(xiàn)這些任務(wù),但是將其轉(zhuǎn)移到這里會(huì)有較好的代碼結(jié)構(gòu),使得操作對(duì)象的準(zhǔn)備工作和執(zhí)行階段分開。isexecuting、isfinished:(必須)并發(fā)操作應(yīng)該建立運(yùn)行環(huán)境并且報(bào)告狀態(tài)給外面的用戶,然而,一個(gè)并發(fā)操作必須維護(hù)一些狀態(tài)信息,來了解何時(shí)開啟任務(wù),何時(shí)完成任務(wù)。這些方法的實(shí)現(xiàn)必須是線程安全的,可能與kvo有關(guān)4。isconcurrent:重載并且返回yes即可。下面的代碼示例簡(jiǎn)單的實(shí)現(xiàn)了如何子類化一個(gè)并發(fā)的操作對(duì)象:/ 子類化 nsoperationinterface myoperation: ns
33、operation bool executing;bool finished;- (void)completeoperation;endimplementation myoperation/ 實(shí)現(xiàn)初始化方法- (id)init self = super init;if (self) executing = no;finished = no;return self;/ 重載操作對(duì)象的并發(fā)性屬性- (bool)isconcurrent return yes;/ 重載實(shí)現(xiàn) kvo- (bool)isexecuting return executing;- (bool)isfinished retur
34、n finished;下面的代碼示例為如何在start方法中做準(zhǔn)備工作,以及實(shí)現(xiàn)kvo:- (void)start / 周期性的檢查是否有取消操作發(fā)生if (self iscancelled) / 如果當(dāng)前操作對(duì)象被取消,那么需要改變finished狀態(tài)信息self willchangevalueforkey:”isfinished”;finished = yes;self didchangevalueforkey:”isfinished”;/ 當(dāng)取消操作發(fā)生時(shí),需要直接返回return;/ 當(dāng)操作對(duì)象沒有被取消時(shí),開始執(zhí)行任務(wù)self willchangevalueforkey:”isexe
35、cuting”;/ 開啟單獨(dú)的線程并執(zhí)行任務(wù)nsthread detachnewthreadselector:selector(main) totarget:self withobject:nil;/ 這個(gè)時(shí)候任務(wù)已經(jīng)開始了,需要改變executing狀態(tài)executing = yes;self didchangevalueforkey:”isexecuting”;當(dāng)編寫完操作對(duì)象的準(zhǔn)備階段的start方法后,就可以開始編寫main方法,將start方法和main方法分開使得代碼有清晰的結(jié)構(gòu),有助于調(diào)試和debug。在main方法中,當(dāng)操作對(duì)象的狀態(tài)改變時(shí),仍需實(shí)現(xiàn)對(duì)象的kvo規(guī)則,如下:-
36、(void)main try / 開始執(zhí)行有關(guān)操作的主任務(wù)/ 執(zhí)行完成后調(diào)用完成操作self completeoperation;catch() / 仍然無需拋出異常- (void)completeoperation self willchangevalueforkey:”isfinished”;self willchangevalueforkey:”isexecuting”;/ 在任務(wù)完成后,需要更改對(duì)應(yīng)的狀態(tài)信息executing = no;finished = yes;self didchangevalueforkey:” isfinished”;self didchangevaluef
37、orkey:” isexecuting”;3.2.4保證kvo規(guī)則nsoperation 對(duì)于以下屬性實(shí)現(xiàn) kvo:iscancelled、isconcurrent、isexecuting、isfinished、isready、dependencies、queuepriority、completionblock。如果對(duì)nsoperation重寫了start方法或者做了其他一些重大的定制,除了重載main方法,還需要確保自定義對(duì)象仍然保證了kvo規(guī)則。如果想要實(shí)現(xiàn)對(duì)其他操作對(duì)象依賴項(xiàng)的支持,可以重載isready方法,直到自定義的依賴項(xiàng)已經(jīng)滿足,不然一直返回no(這里應(yīng)該調(diào)用super),當(dāng)狀態(tài)
38、改變時(shí),通過發(fā)出kvo通知告知狀態(tài)的改變。除非你重寫 adddependency 或 removedependency 方法,不然無需操心dependencies的kvo規(guī)則5。盡管可以生成其他key的 kvo,但是最好不要這樣做。如果需要取消操作對(duì)象,只需調(diào)用其cancel方法即可,同樣,整個(gè)過程可能不需要修改隊(duì)列優(yōu)先級(jí)。最后,除非操作對(duì)象會(huì)動(dòng)態(tài)改變isconcurrent屬性,不然無需實(shí)現(xiàn)其kvo規(guī)則。3.3自定義操作對(duì)象的執(zhí)行行為成功建操作對(duì)象后,在將其添加到隊(duì)列之前,可以對(duì)操作對(duì)象進(jìn)行配置。這一節(jié)中所描述的配置類型既可以應(yīng)用于自定義的繼承于nsoperation類的子類,也可應(yīng)用于系統(tǒng)
39、提供的子類。3.3.1配置操作對(duì)象之間的依賴關(guān)系依賴關(guān)系是一種序列化不同操作對(duì)象的方式。一個(gè)對(duì)象依賴于其他對(duì)象的執(zhí)行狀態(tài),只有當(dāng)其依賴的對(duì)象全部完成時(shí),它自己才可以開始執(zhí)行。因此,可以使用依賴關(guān)系來創(chuàng)立復(fù)雜的執(zhí)行順序。使用nsoperation類的adddependency:方法創(chuàng)建兩個(gè)對(duì)象之間的依賴關(guān)系。這個(gè)方法創(chuàng)建一個(gè)從當(dāng)前對(duì)象到目標(biāo)對(duì)象單向的依賴關(guān)系,其返回結(jié)果可以作為一個(gè)參數(shù)來傳遞。這種依賴性表示當(dāng)前的對(duì)象只有在目標(biāo)對(duì)象完成時(shí)才可以開始執(zhí)行。這種依賴關(guān)系并不局限于同一個(gè)隊(duì)列中的操作對(duì)象,因?yàn)椴僮鲗?duì)象本身管理自己的依賴項(xiàng),所以,完全可以在不同隊(duì)列中的不同操作對(duì)象之間創(chuàng)建依賴關(guān)系。需要注意
40、的是,不要產(chǎn)生循環(huán)依賴的關(guān)系。當(dāng)所有的依賴項(xiàng)都已經(jīng)完成時(shí),當(dāng)前操作對(duì)象將準(zhǔn)備開始執(zhí)行(當(dāng)重載isready方法后,這個(gè)狀態(tài)需要使用自己創(chuàng)建的標(biāo)準(zhǔn))。如果對(duì)象已經(jīng)處于隊(duì)列中,那么隊(duì)列可能隨時(shí)開始執(zhí)行這個(gè)對(duì)象,如果是手動(dòng)管理對(duì)象的執(zhí)行,那么需要調(diào)用操作對(duì)象的start方法。應(yīng)該總是在操作對(duì)象運(yùn)行之前或者添加到隊(duì)列之前配置它的依賴關(guān)系,在運(yùn)行之后添加依賴關(guān)系可能會(huì)無效。依賴關(guān)系依賴于每個(gè)對(duì)象當(dāng)狀態(tài)變化時(shí)發(fā)送kvo通知,當(dāng)自定義對(duì)象的這種行為時(shí),為了避免出錯(cuò),可能需要在代碼中生成對(duì)應(yīng)的kvo通知。3.3.2更改操作執(zhí)行的優(yōu)先級(jí)對(duì)于添加到隊(duì)列的操作對(duì)象,執(zhí)行順序首先取決于已經(jīng)入隊(duì)操作對(duì)象的準(zhǔn)備情況,然后
41、取決于其優(yōu)先級(jí)。準(zhǔn)備情況取決于操作對(duì)象依賴的其他對(duì)象,但是優(yōu)先級(jí)是操作對(duì)象自身的屬性,默認(rèn)情況下,所有新創(chuàng)建的操作對(duì)象都有一個(gè)默認(rèn)的優(yōu)先級(jí),但可以通過setqueuepriority方法增大或者減小優(yōu)先級(jí)。優(yōu)先級(jí)只適用于同一個(gè)隊(duì)列中的不同對(duì)象,如果程序中有多個(gè)操作隊(duì)列,每個(gè)對(duì)象在不同的隊(duì)列中的優(yōu)先級(jí)是相互獨(dú)立的。因此,低優(yōu)先級(jí)的操作對(duì)象可能在不同的隊(duì)列中執(zhí)行得比高優(yōu)先級(jí)的操作對(duì)象要早。優(yōu)先級(jí)不是依賴關(guān)系的替代,優(yōu)先級(jí)只影響某個(gè)隊(duì)列中已經(jīng)做好執(zhí)行準(zhǔn)備的操作對(duì)象,舉個(gè)例子,如果一個(gè)隊(duì)列中,存在已經(jīng)準(zhǔn)備好的兩個(gè)不同優(yōu)先級(jí)的對(duì)象,那么首先執(zhí)行高優(yōu)先級(jí)的,但如果高優(yōu)先級(jí)的還未準(zhǔn)備好,低優(yōu)先級(jí)的已經(jīng)準(zhǔn)備好
42、了,那么首先會(huì)執(zhí)行低優(yōu)先級(jí)的,如果想要使某個(gè)操作對(duì)象必須在另一個(gè)操作對(duì)象執(zhí)行完畢之后才執(zhí)行,那么應(yīng)該使用依賴關(guān)系而不是優(yōu)先級(jí)。3.4開始執(zhí)行操作對(duì)象當(dāng)操作對(duì)象初始化并且配置完成后,需要執(zhí)行它們來完成程序中的工作。3.4.1更改操作執(zhí)行的優(yōu)先級(jí)到目前為止,執(zhí)行操作對(duì)象最簡(jiǎn)單的方式就是將其添加到一個(gè)操作隊(duì)列,應(yīng)用程序本身負(fù)責(zé)創(chuàng)建和維護(hù)需要使用的操作隊(duì)列。程序可以擁有多個(gè)操作隊(duì)列,但如果太多會(huì)有限制。操作隊(duì)列與系統(tǒng)根據(jù)內(nèi)核和系統(tǒng)負(fù)載,決定某一時(shí)刻維持多少并發(fā)的數(shù)量,因此,創(chuàng)建太多的操作隊(duì)列不一定能夠立即執(zhí)行其中的操作對(duì)象。創(chuàng)建隊(duì)列與創(chuàng)建其他對(duì)象的方式一樣??梢允褂胊ddoperation:方法添加操
43、作對(duì)象,同時(shí)還可以使用 addoperationwithblock:方法添加block,所有這些方法均進(jìn)隊(duì)一個(gè)操作對(duì)象并開始執(zhí)行。大多數(shù)情況下,操作對(duì)象會(huì)在添加到隊(duì)列后就開始執(zhí)行,但是仍然還有其他一些原因可能會(huì)導(dǎo)致操作對(duì)象被推遲執(zhí)行。例如某個(gè)操作對(duì)象依賴于其他操作對(duì)象的完成,或者操作隊(duì)列本身是被掛起的,亦或是操作數(shù)超過了隊(duì)列設(shè)置的最大并發(fā)數(shù)。一定要注意當(dāng)操作對(duì)象添加到操作隊(duì)列后,不能去改變它,你可以使用nsoperation類的其他方法來查看它當(dāng)前的狀態(tài)。盡管操作隊(duì)列是并發(fā)的,但是仍然可以通過設(shè)置其最大并發(fā)數(shù)為1使其強(qiáng)制串行執(zhí)行,盡管同一時(shí)間只有一個(gè)操作對(duì)象執(zhí)行,但是其執(zhí)行順序仍然受其他因素的
44、影響,因此串行的操作隊(duì)列并不能提供像gcd一樣的行為,如果串行隊(duì)列中操作對(duì)象之間的執(zhí)行順序很重要,那么使用依賴關(guān)系仍然是最適合的方式。3.4.2手動(dòng)實(shí)行操作對(duì)象盡管操作隊(duì)列可以很方便地執(zhí)行操作對(duì)象,但是有時(shí)候仍希望不通過操作隊(duì)列來執(zhí)行某些操作對(duì)象,下面是一些手動(dòng)執(zhí)行需要注意的地方,最重要的是必須要保證其準(zhǔn)備好執(zhí)行然后調(diào)用其start方法。操作對(duì)象不會(huì)在isready方法返回yes之前執(zhí)行,isready方法取決于其依賴的對(duì)象是否全部執(zhí)行完畢。手動(dòng)執(zhí)行時(shí)必須顯示調(diào)用其start方法,不能使用main或者其他方法,因?yàn)閟tart方法在真正運(yùn)行前做了一些檢查,尤其是start方法中實(shí)現(xiàn)了有關(guān)kvo通
45、知的生成,保證了其他對(duì)象正確的依賴狀態(tài),此方法同時(shí)還保證了在取消之后不去執(zhí)行或者沒有準(zhǔn)備好執(zhí)行時(shí)拋出異常。如果程序中定義了一些并發(fā)的操作對(duì)象,那么應(yīng)該考慮在加載之前調(diào)用其isconcurrent方法,當(dāng)它返回no時(shí),就能夠決定是在當(dāng)前線程同步執(zhí)行操作對(duì)象還是開啟另一個(gè)線程。下面的例子簡(jiǎn)單的示范了手動(dòng)執(zhí)行操作對(duì)象時(shí)的一些檢查工作,當(dāng)方法返回no時(shí),應(yīng)該考慮實(shí)現(xiàn)定時(shí)器來重復(fù)調(diào)用直到返回yes。- (bool)performoperation:(nsoperation *)anopbool ranit = no;/ 檢查操作對(duì)象的狀態(tài)if (anop isready && !anop
46、 iscancelled)/ 當(dāng)操作對(duì)象準(zhǔn)備好并且沒有被取消時(shí)if(!anop isconcurrent) / 操作對(duì)象為串行執(zhí)行時(shí),直接調(diào)用start方法anop start;else nsthread detachnewthreadselector:selector(start) totarget:anop withobject:nil;ranit = yes;else if (anop iscancelled) / 操作對(duì)象被取消,需要發(fā)出kvo通知并且改變執(zhí)行狀態(tài)self willchangevalueforkey:”isfinished”;self willchangevaluefo
47、rkey:”isexecuting”;executing = no;finished = yes;self didchangevalueforkey:” isfinished”;self didchangevalueforkey:” isexecuting”;ranit = yes;return ranit;3.4.3取消操作對(duì)象的執(zhí)行一旦操作對(duì)象添加到操作隊(duì)列后,將由操作隊(duì)列高效地管理并且不能被移除,唯一出隊(duì)的方式就是取消它,可以通過調(diào)用其cancel方法取消單個(gè)的操作對(duì)象,也可以調(diào)用操作隊(duì)列的cancelalloperation方法取消隊(duì)列中所有的操作對(duì)象。只有在確定不再需要時(shí)才取消它,取
48、消其實(shí)相當(dāng)于操作對(duì)象已經(jīng)完成,如果被依賴項(xiàng)被取消,那么這個(gè)依賴關(guān)系就不再成立了。3.4.4等待操作對(duì)象執(zhí)行完成為了程序有更出色的表現(xiàn),應(yīng)該讓操作對(duì)象盡可能的并發(fā),好讓程序能夠去做別的事情,如果創(chuàng)建操作對(duì)象的代碼同時(shí)需要等待執(zhí)行完成來處理執(zhí)行結(jié)果,可以調(diào)用waituntilfinished方法。但是盡量避免使用這個(gè)方法。永遠(yuǎn)不能在程序主線程中等待操作對(duì)象完成,應(yīng)該在工作線程或者其他操作對(duì)象中等待,因?yàn)樽枞骶€程會(huì)使程序遲鈍。除了等待單個(gè)操作對(duì)象完成,也可以等待整個(gè)操作隊(duì)列完成,然后可以繼續(xù)向其添加操作對(duì)象。3.4.5掛起和恢復(fù)操作隊(duì)列如果需要暫停某個(gè)操作對(duì)象的執(zhí)行,可以使用隊(duì)列的setsuspe
49、nded方法,掛起隊(duì)列不會(huì)影響已經(jīng)執(zhí)行的操作對(duì)象,只會(huì)暫停新添加到隊(duì)列中的操作對(duì)象。第四章 調(diào)度隊(duì)列在ios平臺(tái)中,gcd 調(diào)度隊(duì)列是執(zhí)行任務(wù)的強(qiáng)大工具,可以使用同步或異步方式執(zhí)行任意的代碼塊。調(diào)度隊(duì)列可以執(zhí)行幾乎所有的單線程代碼。相比于線程級(jí)別代碼,其更易于使用,且效率要高。本章節(jié)將介紹調(diào)度隊(duì)列,以及如何使用它執(zhí)行大多數(shù)任務(wù)。4.1調(diào)度隊(duì)列介紹調(diào)度隊(duì)列是在程序中執(zhí)行同步或異步代碼的比較簡(jiǎn)單的一種方式,任務(wù)就是程序中需要執(zhí)行的一些簡(jiǎn)單的工作,例如執(zhí)行一些計(jì)算,創(chuàng)建或修改一個(gè)數(shù)據(jù)結(jié)構(gòu),從文件中讀取數(shù)據(jù)并進(jìn)行處理等等這樣的一些工作。通過在函數(shù)或block中寫入相應(yīng)的代碼來定義任務(wù),然后將其添加至調(diào)
50、度隊(duì)列開始執(zhí)行。調(diào)度隊(duì)列是一種類似對(duì)象的結(jié)構(gòu),它管理提交到它上的任務(wù)。所有的調(diào)度隊(duì)列都是先進(jìn)先出的,因此任務(wù)開始執(zhí)行的順序與添加順序一致。gcd已經(jīng)提供了一些常用的調(diào)度隊(duì)列,也可以根據(jù)自己的需求創(chuàng)建自定義調(diào)度隊(duì)列。當(dāng)程序中引入并發(fā)性時(shí),相比較線程而言,調(diào)度隊(duì)列提供了幾個(gè)特有的優(yōu)勢(shì)。最直接的優(yōu)勢(shì)就是簡(jiǎn)單的工作隊(duì)列以及編程模型。使用線程時(shí),不僅需要編寫執(zhí)行任務(wù)所需的代碼,還需創(chuàng)建和管理自己創(chuàng)建的線程。調(diào)度隊(duì)列能夠讓開發(fā)者更加專注于任務(wù)的處理,而無需擔(dān)心線程的管理和創(chuàng)建。相反,操作系統(tǒng)會(huì)做所有線程相關(guān)創(chuàng)建和管理的工作。相比于應(yīng)用程序本身,操作系統(tǒng)能夠更加高效地管理線程,系統(tǒng)能夠根據(jù)可用的資源以及當(dāng)前
51、的并發(fā)線程數(shù)量,動(dòng)態(tài)地?cái)U(kuò)展正在運(yùn)行線程的數(shù)量。此外,系統(tǒng)提供的線程通常會(huì)比自己創(chuàng)建的線程更快地開始執(zhí)行。使用調(diào)度隊(duì)列編碼要比線程簡(jiǎn)單的多,其編碼的關(guān)鍵是設(shè)計(jì)能夠異步執(zhí)行且資源就緒的任務(wù)。然而,調(diào)度隊(duì)列還有個(gè)優(yōu)點(diǎn)是可預(yù)測(cè)性,如果有兩個(gè)不同的線程需要存取同一份資源,那么每個(gè)線程都有可能先修改這份資源,所以需要使用鎖來保證兩個(gè)線程不會(huì)同時(shí)修改這份資源。而使用調(diào)度隊(duì)列時(shí),可以將這兩個(gè)任務(wù)添加進(jìn)同一條串行隊(duì)列來確保同時(shí)只有一個(gè)任務(wù)可以修改資源。這種基于同步機(jī)制的隊(duì)列要比鎖的效率更高一些,因?yàn)殒i不管是不是在競(jìng)爭(zhēng)條件下都需要一個(gè)昂貴的內(nèi)核中斷。而調(diào)度隊(duì)列運(yùn)行在自己的程序空間中,只有在必要時(shí)才會(huì)中斷內(nèi)核。下面
52、是調(diào)度隊(duì)列其他一些需要重點(diǎn)關(guān)注的地方:1. 所有調(diào)度隊(duì)列同時(shí)執(zhí)行它們隊(duì)列中的任務(wù),只有單個(gè)隊(duì)列中才會(huì)執(zhí)行序列化的任務(wù)。2. 系統(tǒng)決定同一時(shí)間類可以執(zhí)行任務(wù)的總數(shù)。3. 系統(tǒng)在選取新的任務(wù)執(zhí)行時(shí)會(huì)考慮隊(duì)列的優(yōu)先級(jí)。 4. 添加到隊(duì)列的任務(wù)必須滿足可以執(zhí)行的條件,比如資源就緒等。下面列出了幾種調(diào)度隊(duì)列,并相應(yīng)做了簡(jiǎn)要的說明。4.1.1串行隊(duì)列(serial queue)串行隊(duì)列,也稱私有調(diào)度隊(duì)列,執(zhí)行順序?yàn)槿蝿?wù)添加的順序。當(dāng)前正在執(zhí)行的任務(wù)運(yùn)行在別的線程上(具體跟任務(wù)類型有關(guān)),并且由調(diào)度隊(duì)列直接進(jìn)行管理。串行隊(duì)列經(jīng)常用來執(zhí)行一些同步操作,比如對(duì)于指定資源的存取。4.1.2并行隊(duì)列(concurr
53、ent queue)并行隊(duì)列,也稱全局隊(duì)列,可以同時(shí)執(zhí)行一個(gè)或多個(gè)任務(wù)。但任務(wù)仍然按照添加的順序執(zhí)行,當(dāng)前的任務(wù)運(yùn)行在不同的線程上,這些線程由調(diào)度隊(duì)列管理。某個(gè)時(shí)刻正在執(zhí)行的任務(wù)數(shù)量是變化的,取決于操作系統(tǒng)當(dāng)前的狀態(tài)。在ios 5以后,可以指定調(diào)度隊(duì)列類型為 dispatch_queue_concurrent來創(chuàng)建自己的并發(fā)調(diào)度隊(duì)列,除此之外,系統(tǒng)已經(jīng)提供了四個(gè)預(yù)先定義的調(diào)度隊(duì)列供使用。4.1.3主調(diào)度隊(duì)列(main dispatch queue)主調(diào)度隊(duì)列是全局可用的串行隊(duì)列,在程序的主線程上執(zhí)行任務(wù)。與應(yīng)用程序的其他事件執(zhí)行交織在一起加入到主線程的runloop中。由于隊(duì)列運(yùn)行在主線程中,所以經(jīng)常用作一些關(guān)鍵的同步點(diǎn)。盡管不需要?jiǎng)?chuàng)建自己的主隊(duì)列,但是需要確保程序能夠在主線程中快速地執(zhí)行完所添加的任務(wù),因?yàn)楹臅r(shí)的操作會(huì)阻塞ui,使得程序變得卡頓。4.2與隊(duì)列相關(guān)的一些技術(shù)點(diǎn)除了調(diào)度隊(duì)列外,gcd還提供了有關(guān)使用隊(duì)列編碼的一些技術(shù),具體如下:dispatch group:用來觀察一組block對(duì)象的完成。它提供了一種非常有用的同步機(jī)制,依賴其他任務(wù)的完成。dispatch semaphores:類似于傳統(tǒng)的信號(hào)量,通常要高效一
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 西安郵電大學(xué)《美術(shù)鑒賞與批評(píng)》2023-2024學(xué)年第二學(xué)期期末試卷
- 浙江理工大學(xué)《木材工業(yè)自動(dòng)化》2023-2024學(xué)年第二學(xué)期期末試卷
- 南昌大學(xué)共青學(xué)院《免疫學(xué)與病原生物學(xué)》2023-2024學(xué)年第二學(xué)期期末試卷
- 撫順師范高等專科學(xué)?!镀放菩蜗髮m?xiàng)設(shè)計(jì)一》2023-2024學(xué)年第二學(xué)期期末試卷
- 證券從業(yè)資格證券投資顧問勝任能力考試證券投資顧問業(yè)務(wù)真題1
- 山東勞動(dòng)職業(yè)技術(shù)學(xué)院《智能車輛環(huán)境感知技術(shù)》2023-2024學(xué)年第二學(xué)期期末試卷
- 2025遼寧省安全員B證(項(xiàng)目經(jīng)理)考試題庫
- 湖南冶金職業(yè)技術(shù)學(xué)院《企業(yè)生產(chǎn)與技術(shù)管理》2023-2024學(xué)年第二學(xué)期期末試卷
- 2025年陜西省建筑安全員-B證(項(xiàng)目經(jīng)理)考試題庫
- 湖南電氣職業(yè)技術(shù)學(xué)院《面向數(shù)據(jù)科學(xué)的語言》2023-2024學(xué)年第二學(xué)期期末試卷
- 手術(shù)部位感染預(yù)防控制措施
- 社會(huì)學(xué)概論課件
- 中醫(yī)類診所規(guī)章制度與崗位職責(zé)
- 初中語文 中考總復(fù)習(xí)-文言文斷句訓(xùn)練120題(含答案解析)
- 影視鑒賞-動(dòng)畫電影課件
- 美學(xué)原理全套教學(xué)課件
- 精裝修施工圖深化內(nèi)容及要求
- 《克雷洛夫寓言》閱讀指導(dǎo)課件
- 《無人機(jī)載荷與行業(yè)應(yīng)用》 課件全套 第1-6章 無人機(jī)任務(wù)載荷系統(tǒng)概述- 未來展望與挑戰(zhàn)
- 《室內(nèi)照明設(shè)計(jì)》(熊杰)794-5 教案 第7節(jié) 綠色照明、節(jié)能照明與應(yīng)急照明
- 腦卒中后認(rèn)知障礙的護(hù)理課件
評(píng)論
0/150
提交評(píng)論