自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

詳解IOS開發(fā)應(yīng)用之并發(fā)Dispatch Queues

移動開發(fā) iOS
詳解IOS開發(fā)應(yīng)用之并發(fā)Dispatch Queues是本文喲啊介紹的內(nèi)容,我們幾乎可以調(diào)度隊列去完成所有用線程來完成的任務(wù)。

詳解IOS開發(fā)應(yīng)用之并發(fā)Dispatch Queues是本文喲啊介紹的內(nèi)容,我們幾乎可以調(diào)度隊列去完成所有用線程來完成的任務(wù)。調(diào)度隊列相對于線程代碼更簡單,易于使用,更高效。下面講主要簡述調(diào)度隊列,在應(yīng)用中如何使用調(diào)度隊列去執(zhí)行任務(wù)。

1、關(guān)于調(diào)度隊列

所有的調(diào)度隊列都是先進(jìn)先出隊列,因此,隊列中的任務(wù)的開始的順序和添加到隊列中的順序相同。GCD自動的為我們提供了一些調(diào)度隊列,我們也可以創(chuàng)建新的用于具體的目的。

下面列出幾種可用的調(diào)度隊列類型以及如何使用。

(1)serial queues(串行隊列)又稱私有調(diào)度隊列(private),一般用再對特定資源的同步訪問上。我們可以根據(jù)需要創(chuàng)建任意數(shù)量的串行隊列,每一個串行隊列之間是并發(fā)的。

(2)并行隊列,又稱global dispatch queue。并行隊列雖然可以并發(fā)的執(zhí)行多個任務(wù),但是任務(wù)開始執(zhí)行的順序和其加入隊列的順序相同。我們自己不能去創(chuàng)建并行調(diào)度隊列。只有三個可用的global concurrent queues。

(3)main dispatch queue 是一個全局可用的串行隊列,其在行用程序的主線程上執(zhí)行任務(wù)。此隊列的任務(wù)和應(yīng)用程序的主循環(huán)(run loop)要執(zhí)行的事件源交替執(zhí)行。因為其運行在應(yīng)用程序的主線程,main queue經(jīng)常用來作為應(yīng)用程序的一個同步點。

2、關(guān)于隊列的一些技術(shù)

除了調(diào)度隊列,GCD還提供了一些有用的技術(shù)來幫助我們管理代碼。

  1. dispath group ,dispatch semaphore, dispath sources 

3、使用blocks去實現(xiàn)tasks

block objects是基于C語言的特征,可以用在C,C++ Objective-c中。一個block雖然和函數(shù)指針有些相似,但是實際上代表一個底層數(shù)據(jù)結(jié)構(gòu),類似與對象,有編譯器去創(chuàng)建和管理。

block的一個優(yōu)勢是可以使用其自己作用域外的變量,例如,一個block可以讀取其父作用域的變量值,此值是copy到了block heap的數(shù)據(jù)結(jié)構(gòu)中。當(dāng)block被加入到dispatch queue中,這些值通常為只讀形式。

block的聲明和函數(shù)指針類似,只是把*改為了^,我們可以傳遞參數(shù)給block,也可以接收其返回的值。

4、創(chuàng)建和管理調(diào)度隊列

(1)獲得全局并發(fā)調(diào)度隊列(global concurrent dispath queues)

系統(tǒng)給每一個應(yīng)用程序提供了三個concurrent dispatch queues。這三個并發(fā)調(diào)度隊列是全局的,它們只有優(yōu)先級的不同。因為是全局的,我們不需要去創(chuàng)建。我們只需要通過使用函數(shù)dispath_get_global_queue去得到隊列,如下:

  1. dispatch_queue_t aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);  

除了得到default的并發(fā)隊列,還可以通過傳遞參數(shù)DISPATCH_QUEUE_PRIOPITY_HIGH和DISPATCH_QUEUE_PRIOPITY_LOW去得到高優(yōu)先級或者低優(yōu)先級的。(第二個參數(shù)是為以后擴(kuò)展保留的)

雖然dispatch queue是引用計數(shù)對象,但是在此因為隊列是全局的,不需要我們?nèi)etain或者release,我們需要使用的時候直接調(diào)用函數(shù)dispath_get_global_queue就可以。

(2)創(chuàng)建串行調(diào)度隊列

當(dāng)想要任務(wù)按照某一個特定的順序執(zhí)行時,串行隊列是很有用的。串行隊列在同一個時間只執(zhí)行一個任務(wù)。我們可以使用串行隊列代替鎖去保護(hù)共享的數(shù)據(jù)。和鎖不同,一個串行隊列可以保證任務(wù)在一個可預(yù)知的順序下執(zhí)行。

和并發(fā)隊列不同,我們要自己去創(chuàng)建和管理串行隊列,可以創(chuàng)建任意數(shù)量的串行隊列。當(dāng)我們創(chuàng)建串行隊列時,應(yīng)出于某種目的,如保護(hù)資源,或者同步應(yīng)用程序的某些關(guān)鍵行為。

下面的代碼表述了怎么創(chuàng)建一個自定義的串行隊列,函數(shù)dispath_queue_create需要兩個參數(shù),隊列的名字,隊列的屬性。調(diào)試器和性能工具顯示隊列的名字幫助我們?nèi)ジ櫲蝿?wù)是如何執(zhí)行,隊列的屬性被保留供將來使用,應(yīng)該為NULL

  1. dispatch_queue_t queue;  
  2. queue = dispatch_queue_create("com.example.MyQueue", NULL); 

除了自己創(chuàng)建的自定義隊列,系統(tǒng)會自動的給我創(chuàng)建一個串行隊列并和應(yīng)用程序的主線程綁定到一起。下面講述如何獲得它。

(3)運行時獲得常見的隊列

GCD提供了一些函數(shù)讓我們能夠方便的訪問到common dispatch queues

使用dispatch_get_current_queue函數(shù)用來調(diào)試或者測試獲得當(dāng)前隊列的標(biāo)識。
  
使用函數(shù)dispatch_get_main_queue可以得到與應(yīng)用程序主線程相連的串行調(diào)度隊列。

(4)調(diào)度隊列的內(nèi)存管理

調(diào)度隊列是引用計數(shù)類型,當(dāng)我們創(chuàng)建串行調(diào)度隊列時,我們要release它。可以使用函數(shù)dispatch_retain和dispatch_release去增加或者減少引用計數(shù)。

(5)在一個隊列中存儲自定義context information

所有的調(diào)度對象允許我們讓其與一個自定義上下文數(shù)據(jù)關(guān)聯(lián),通過函數(shù)dispatch_set_context和dispatch_get_context來使用,系統(tǒng)不會去使用我們的自定義數(shù)據(jù),我們自己在恰當(dāng)?shù)臅r間去分配和釋放。

對于隊列,上下文數(shù)據(jù)通常用來存儲一個指向?qū)ο蟮闹羔?,或者其他的?shù)據(jù)結(jié)構(gòu),我們可以在隊列的finalizer函數(shù)中去釋放context data。下面將給一個例子。

(6)為隊列提供一個clean up 函數(shù)。

當(dāng)我們創(chuàng)建串行調(diào)度隊列之后,我們可以讓其和一個finalizer函數(shù)相連用來清理隊列中需要清理的數(shù)據(jù)。我們可以使用dispatch_set_finalizer_f函數(shù)去設(shè)置一個函數(shù),當(dāng)隊列的引用計數(shù)為0時會去自動的調(diào)用。使用此函數(shù)去清理和隊列相關(guān)聯(lián)的context data,當(dāng)context 指針不會NULL時,此函數(shù)就會調(diào)用。

 

  1. shows a custom finalizer function and a function that creates a queue and installs that finalizer.   
  2. The queue uses the finalizer function to release the data stored in the queue’s context pointer.   
  3. (The myInitializeDataContextFunction and myCleanUpDataContextFunction functions referenced from the code are custom functions that   
  4. you would provide to initialize and clean up the contents of the data structure itself.)   
  5. The context pointer passed to the finalizer function contains the data object associated with the queue. 
  1. void myFinalizerFunction(void *context)  
  2. {  
  3. MyDataContext* theData = (MyDataContext*)context;  
  4. // Clean up the contents of the structure  
  5. myCleanUpDataContextFunction(theData);  
  6. // Now release the structure itself.  
  7. free(theData);  
  8. }  
  9. dispatch_queue_t createMyQueue()  
  10. {  
  11. MyDataContext* data = (MyDataContext*) malloc(sizeof(MyDataContext));  
  12. myInitializeDataContextFunction(data);  
  13. // Create the queue and set the context data.  
  14. dispatch_queue_t serialQueue = dispatch_queue_create("com.example.CriticalTaskQueue", NULL);  
  15. if (serialQueue)  
  16. {  
  17. dispatch_set_context(serialQueue, data);  
  18. dispatch_set_finalizer_f(serialQueue, &myFinalizerFunction);  
  19. }  
  20. return serialQueue;  

5、在隊列中添加一個任務(wù)

(1)有兩種方式在隊列中添加一個任務(wù),同步或者異步。盡可能使用dispatch_async和dispatch_async_f 函數(shù)去執(zhí)行,比同步的要***。當(dāng)我們向隊列中添加一個塊對象或者函數(shù)時,我們沒有方法去知道此代碼什么時間執(zhí)行。

使用此異步不會去阻塞主線程。

雖然盡可能異步添加任務(wù),在有些時候同步的方式去添加一個任務(wù)會防止一些同步錯誤。同步的方式調(diào)用函數(shù)dispatch_sync和dispatch_sync_f。此函數(shù)阻塞主線程的執(zhí)行,直到指定的任務(wù)完成。

下面是代碼例子:

 (2)在任務(wù)完成的時候執(zhí)行completion block

當(dāng)任務(wù)完成時,我們應(yīng)用程序需要得到通知,一遍去合并結(jié)果,在傳統(tǒng)的異步編程中,我們可能會使用回調(diào)函數(shù),但是在調(diào)度隊列中,我們使用completion block。

  1. void average_async(int *data, size_t len,  
  2.  
  3. dispatch_queue_t queue, void (^block)(int))  
  4. {  
  5. // Retain the queue provided by the user to make  
  6. // sure it does not disappear before the completion  
  7. // block can be called.  
  8. dispatch_retain(queue);  
  9. // Do the work on the default concurrent queue and then  
  10. // call the user-provided block with the results.  
  11. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{  
  12. int avg = average(data, len);  
  13. dispatch_async(queue, ^{ block(avg);});  
  14. // Release the user-provided queue when done  
  15. dispatch_release(queue);  
  16. });  

(3)并發(fā)的執(zhí)行循環(huán)迭代(loop iterations)

對于for循環(huán),如果每一次的迭代相互都沒有影響,可以并發(fā)的去執(zhí)行迭代,使用函數(shù)dispatch_apply或者dispatch_apply_f 函數(shù).

和正常的循環(huán)一樣,函數(shù)dispatch_apply或者dispatch_apply_f直到所有的循環(huán)迭代完成時才返回。

如下代碼:

  1. dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);  
  2. dispatch_apply(count, queue, ^(size_t i) {  
  3. printf("%un",i);  
  4. }); 

(4)在主線程上執(zhí)行任務(wù)

我們可以通過調(diào)用函數(shù)dispatch_get_main_queue 去去得到主線程的調(diào)度隊列。

小結(jié):詳解IOS開發(fā)應(yīng)用之并發(fā)Dispatch Queues的內(nèi)容介紹完了,希望通過本文的學(xué)習(xí)能對你有所幫助!

責(zé)任編輯:zhaolei 來源: 互聯(lián)網(wǎng)
相關(guān)推薦

2011-08-17 14:30:34

iOS開發(fā)窗口

2011-08-17 14:20:21

IOS開發(fā)GraphicsCon

2011-08-11 17:32:51

iPhone視圖

2011-08-17 14:07:43

IOS開發(fā)Quartz 2D

2011-08-11 10:16:23

iPhoneUIView視圖

2011-08-11 10:27:37

iPhoneUIView視圖

2011-08-10 10:23:20

iPhoneArchivingNSCoder

2011-08-22 16:26:25

IOS開發(fā)Sqlite數(shù)據(jù)庫

2011-08-16 19:02:23

iPhone開發(fā)繪圖

2011-08-15 18:02:32

iPhone開發(fā)表視圖

2017-02-14 10:00:19

Java開發(fā)Lock

2011-08-11 11:51:07

iPhone鍵盤

2011-08-12 11:31:46

iPhoneUIView動畫

2011-08-15 10:15:00

iPhone開發(fā)警告框

2011-08-02 11:07:42

iOS開發(fā) UIWebView

2018-08-15 12:43:52

iOSAndroid設(shè)計差異

2011-05-11 10:02:37

iOS

2011-08-19 14:27:29

iPhone開發(fā)

2009-07-15 09:59:36

MyEclipse使用

2009-07-15 09:59:36

MyEclipse使用
點贊
收藏

51CTO技術(shù)棧公眾號