iOS開發之GCD

   GCD,全稱Grand Central Dispath,是蘋果開發的一種支持並行操做的機制。它的主要部件是一個FIFO隊列和一個線程池,前者用來添加任務,後者用來執行任務。html

     GCD中的FIFO隊列稱爲dispatch queue,它能夠保證先進來的任務先獲得執行(但不保證必定先執行結束)。ios

     經過與線程池的配合,dispatch queue分爲下面兩種:併發

  •      Serial Dispatch Queue -- 線程池只提供一個線程用來執行任務,因此後一個任務必須等到前一個任務執行結束才能開始。
  •      Concurrent Dispatch Queue -- 線程池提供多個線程來執行任務,因此能夠按序啓動多個任務併發執行。

1. Basic Managementapp

     咱們能夠經過dispatch_queue_cretae來建立隊列,而後用dispatch_release釋放。好比下面兩段代碼分別建立串行隊列和並行隊列:異步

dispatch_queue_t serialQ = dispatch_queue_create("eg.gcd.SerialQueue", DISPATCH_QUEUE_SERIAL);  
dispatch_async(serialQ, ^{  
    // Code here  
});  
dispatch_release(serialQ);  
  
dispatch_queue_t concurrentQ = dispatch_queue_create("eg.gcd.ConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);  
dispatch_async(concurrentQ, ^{  
    // Code here  
});  
dispatch_release(concurrentQ);  

     而系統默認就有一個串行隊列main_queue和並行隊列global_queue:async

dispatch_queue_t globalQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_queue_t mainQ = dispatch_get_main_queue();

   一般,咱們能夠在global_queue中作一些long-running的任務,完成後在main_queue中更新UI,避免UI阻塞,沒法響應用戶操做:ide

 

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // long-running task
    dispatch_async(dispatch_get_main_queue(), ^{
        // update UI
    });
});

     上面提到dispatch_async這個接口,用來提交blcok給指定queue進行異步執行。這個接口會在成功提交block後當即返回,而後繼續執行下去。因爲block是定義在棧上的,因此須要將其複製到堆上,見這裏函數

 

     與之相對應的是dispatch_sync接口,提交block以供同步執行。這個接口會等到block執行結束才返回,因此不須要複製block。So,若是在調用該接口在當前queue上指派任務,就會致使deadlock。維基百科上給了段示例代碼:測試

dispatch_queue_t exampleQueue = dispatch_queue_create("com.example.unique.identifier", NULL );
dispatch_sync( exampleQueue,^{
  dispatch_sync( exampleQueue,^{
    printf("I am now deadlocked...\n");
  });});
dispatch_release( exampleQueue );

     若是追求的是併發,那麼dispatch_sync有什麼用呢?關於dispatch_sync的用途,SO上有討論動畫

 

2. Normal Control

  • dispatch_once

     若是沒有記錯的話,在iOS Con 2012上,大衆點評的同窗分享了個Topic叫《iOS開發最佳實踐》,開篇講singleton實現的演進(怎麼演進都有能夠挑的刺),後面轉折說要把精力放到用戶看獲得的地方。

     若是把singleton和best practice放在一塊兒,那麼我很容易聯想到dispatch_once這個函數,它能夠保證整個應用程序生命週期中某段代碼只被執行一次

static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    // code to be executed once
});
  • dispatch_after

     有時候咱們須要等個幾秒鐘而後作個動畫或者給個提示,這時候能夠用dispatch_after這個函數:

double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    // code to be executed on the main queue after delay
});
  • dispatch_set_target_queue

     經過dispatch_set_target_queue函數能夠設置一個dispatch queue的優先級,或者指定一個dispatch source相應的事件處理提交到哪一個queue上。

dispatch_set_target_queue(serialQ, globalQ);  
  • dispatch_apply

     執行某個代碼片斷若干次。

dispatch_apply(10, globalQ, ^(size_t index) {  
    // do sth. 10 times  
});  
  • dispatch group

     Dispatch Group機制容許咱們監聽一組任務是否完成:

dispatch_group_t group = dispatch_group_create();  
dispatch_group_async(group, concurrentQ, blk0);  
dispatch_group_async(group, concurrentQ, blk1);  
dispatch_group_async(group, concurrentQ, blk2);  
dispatch_group_notify(group, mainQ, ^{  
    // update UI  
});  
dispatch_release(group);  

  或者說同步地等待一段時間看是否結束:

dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 1ull * NSEC_PER_SEC);  
dispatch_group_wait(group, time);  
  • dispatch_barrier_async

     經過dispatch_barrier_async函數提交的任務會等它前面的任務執行結束纔開始,而後它後面的任務必須等它執行完畢才能開始。

dispatch_async(concurrentQ, blk0);  
dispatch_async(concurrentQ, blk1);  
dispatch_barrier_async(concurrentQ, blk_barrier);  
dispatch_async(concurrentQ, blk2);  

原文連接:http://blog.csdn.net/jasonblog/article/details/7816999

 

最後,推薦一個神器。

內測寶

內測寶我的以爲比TestFlight更簡單好用,開發者只須要簡單把打好的ipa包上傳上去,生成二維碼,測試人員在手機上掃碼二維碼,就能夠直接安裝最新的測試版本了,好用的讓人想哭。

相關文章
相關標籤/搜索