GCD,全稱Grand Central Dispath,是蘋果開發的一種支持並行操做的機制。它的主要部件是一個FIFO隊列和一個線程池,前者用來添加任務,後者用來執行任務。html
GCD中的FIFO隊列稱爲dispatch queue,它能夠保證先進來的任務先獲得執行(但不保證必定先執行結束)。ios
經過與線程池的配合,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
若是沒有記錯的話,在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這個函數:
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 queue的優先級,或者指定一個dispatch source相應的事件處理提交到哪一個queue上。
dispatch_set_target_queue(serialQ, globalQ);
執行某個代碼片斷若干次。
dispatch_apply(10, globalQ, ^(size_t index) { // do sth. 10 times });
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_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包上傳上去,生成二維碼,測試人員在手機上掃碼二維碼,就能夠直接安裝最新的測試版本了,好用的讓人想哭。