iOS多線程系列(三)----Dispatch Queues

來源:互聯網
上載者:User

標籤:style   blog   http   io   color   ar   os   使用   for   

轉載自:http://blog.sina.com.cn/s/blog_6dce99b10101atsu.html,尊重原創!

 

詳解IOS開發應用之並發Dispatch Queues是本文要介紹的內容,我們幾乎可以調度隊列去完成所有用線程來完成的任務。調度隊列相對於線程代碼更簡單,便於使用,更高效。下面講主要簡述調度隊列,在應用中如何使用調度隊列去執行任務。

1、關於調度隊列

所有的調度隊列都是先進先出隊列,因此,隊列中的任務的開始的順序和添加到隊列中的順序相同。GCD自動的為我們提供了一些調度隊列,我們也可以建立新的用於具體的目的。

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

(1)serial queues(串列隊列)又稱私人調度隊列(private),一般用再對特定資源的同步訪問上。我們可以根據需要建立任意數量的串列隊列,每一個串列隊列之間是並發的。

(2)並行隊列,又稱global dispatch queue。並行隊列雖然可以並發的執行多個任務,但是任務開始執行的順序和其排入佇列的順序相同。我們自己不能去建立並行調度隊列。只有三個可用的global concurrent queues。

(3)main dispatch queue 是一個全域可用的串列隊列,其在行用程式的主線程上執行任務。此隊列的任務和應用程式的主迴圈(run loop)要執行的事件來源交替執行。因為其運行在應用程式的主線程,main queue經常用來作為應用程式的一個同步點。

2、關於隊列的一些技術

除了調度隊列,GCD還提供了一些有用的技術來協助我們管理代碼。


  1. dispath group ,dispatch semaphore, dispath sources 

3、使用blocks去實現tasks

block objects是基於C語言的特徵,可以用在C,C++ Objective-c中。一個block雖然和函數指標有些相似,但是實際上代表一個底層資料結構,類似與對象,有編譯器去建立和管理。

block的一個優勢是可以使用其自己範圍外的變數,例如,一個block可以讀取其父範圍的變數值,此值是copy到了block heap的資料結構中。當block被加入到dispatch queue中,這些值通常為唯讀形式。

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

4、建立和管理調度隊列

(1)獲得全域並發調度隊列(global concurrent dispath queues)

系統給每一個應用程式提供了三個concurrent dispatch queues。這三個並發調度隊列是全域的,它們只有優先順序的不同。因為是全域的,我們不需要去建立。我們只需要通過使用函數dispath_get_global_queue去得到隊列,如下:


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

除了得到default的並發隊列,還可以通過傳遞參數DISPATCH_QUEUE_PRIOPITY_HIGH和DISPATCH_QUEUE_PRIOPITY_LOW去得到高優先順序或者低優先順序的。(第二個參數是為以後擴充保留的)

雖然dispatch queue是引用計數對象,但是在此因為隊列是全域的,不需要我們去retain或者release,我們需要使用的時候直接調用函數dispath_get_global_queue就可以。

(2)建立串列調度隊列

當想要任務按照某一個特定的順序執行時,串列隊列是很有用的。串列隊列在同一個時間只執行一個任務。我們可以使用串列隊列代替鎖去保護共用的資料。和鎖不同,一個串列隊列可以保證任務在一個可預知的順序下執行。

和並發隊列不同,我們要自己去建立和管理串列隊列,可以建立任意數量的串列隊列。當我們建立串列隊列時,應出於某種目的,如保護資源,或者同步應用程式的某些關鍵行為。

下面的代碼錶述了怎麼建立一個自訂的串列隊列,函數dispath_queue_create需要兩個參數,隊列的名字,隊列的屬性。調試器和效能工具顯示隊列的名字協助我們去跟蹤任務是如何執行,隊列的屬性被保留供將來使用,應該為NULL


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

除了自己建立的自訂隊列,系統會自動的給我建立一個串列隊列並和應用程式的主線程綁定到一起。下面講述如何獲得它。

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

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

使用dispatch_get_current_queue函數用來調試或者測試獲得當前隊列的標識。
   
使用函數dispatch_get_main_queue可以得到與應用程式主線程相連的串列調度隊列。

(4)調度隊列的記憶體管理

調度隊列是引用計數類型,當我們建立串列調度隊列時,我們要release它。可以使用函數dispatch_retain和dispatch_release去增加或者減少引用計數。

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

所有的調度對象允許我們讓其與一個自訂上下文資料關聯,通過函數dispatch_set_context和dispatch_get_context來使用,系統不會去使用我們的自訂資料,我們自己在恰當的時間去分配和釋放。

對於隊列,上下文資料通常用來儲存一個指向對象的指標,或者其他的資料結構,我們可以在隊列的finalizer函數中去釋放context data。下面將給一個例子。

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

當我們建立串列調度隊列之後,我們可以讓其和一個finalizer函數相連用來清理隊列中需要清理的資料。我們可以使用dispatch_set_finalizer_f函數去設定一個函數,當隊列的引用計數為0時會去自動的調用。使用此函數去清理和隊列相關聯的context data,當context 指標不會NULL時,此函數就會調用。

 


  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、在隊列中添加一個任務

(1)有兩種方式在隊列中添加一個任務,同步或者非同步。儘可能使用dispatch_async和dispatch_async_f 函數去執行,比同步的要首選。當我們向隊列中添加一個塊對象或者函數時,我們沒有方法去知道此代碼什麼時間執行。

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

雖然儘可能非同步新增工作,在有些時候同步的方式去添加一個任務會防止一些同步錯誤。同步的方式調用函數dispatch_sync和dispatch_sync_f。此函數阻塞主線程的執行,直到指定的任務完成。

下面是代碼例子:

(2)在任務完成的時候執行completion block

當任務完成時,我們應用程式需要得到通知,一遍去合并結果,在傳統的非同步編程中,我們可能會使用回呼函數,但是在調度隊列中,我們使用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)並發的執行迴圈迭代(loop iterations)

對於for迴圈,如果每一次的迭代相互都沒有影響,可以並發的去執行迭代,使用函數dispatch_apply或者dispatch_apply_f 函數.

和正常的迴圈一樣,函數dispatch_apply或者dispatch_apply_f直到所有的迴圈迭代完成時才返回。

如下代碼:


  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)在主線程上執行任務

我們可以通過調用函數dispatch_get_main_queue 去去得到主線程的調度隊列。

小結:詳解IOS開發應用之並發Dispatch Queues的內容介紹完了,希望通過本文的學習能對你有所協助!

---恢複內容結束---

iOS多線程系列(三)----Dispatch Queues

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.