本文複製、參考自文章:iOS多線程編程之Grand Central Dispatch(GCD)介紹和使用 ,主要爲了增強我的對知識的理解和記憶,不作他用。原做者聲明:html
著做權聲明:本文由http://blog.csdn.net/totogo2010/原創,歡迎轉載分享。請尊重做者勞動,轉載時保留該聲明和做者博客連接,謝謝!ios
這裏對原做者的辛勤工做表示感謝!數據庫
GCD (Grand Central Dispatch) 是創建任務並行執行的線程池模式的基礎上的,以優化支持多核、多處理器系統。編程
GCD的工做原理是:讓程序平行排隊的特定任務,根據可用的處理資源,安排他們在任何可用的核心上執行任務。一個任務能夠是一個函數(function)或者是一個block。網絡
GCD的底層依然是用線程實現,不過沒必要關心實現細節。多線程
GCD的FIFO隊列稱爲 調度隊列(dispatch queue), 它能夠保證先來的先執行。dispatch 的、queue 分爲如下3種:併發
又稱爲 私有調度隊列(pirvate dispatch queue), 同時只執行一個任務。Serial queue一般用於同步訪問特定的資源或數據。當建立多個Serial queue時,雖然它們各自隊列內是單獨執行的,但隊列間是併發執行的。app
又稱爲 全局調度隊列(global dispatch queue), 能夠併發地執行隊列中的多個任務,可是執行完成的順序是隨機的。異步
它是全局可用的serial queue,是在應用程序主線程上執行任務的。async
爲了不界面在處理耗時的操做時卡死,好比讀取網絡數據、IO、數據庫讀寫等,咱們會在另外一個線程中去處理這些操做,而後通知主線程更新界面。
用GCD實現這個流程比前面介紹的NSThread\NSOperation的方法都要簡單,代碼以下:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 耗時的操做 dispatch_async(dispatch_get_main_queue(), ^{ // 更新界面 }); });
針對以前圖片加載的示例:
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. // NSThread* thread = [[NSThread alloc] initWithTarget:self selector:@selector(downloadImage:) object:kURL]; // [thread start]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSURL* url = [NSURL URLWithString:kURL]; NSData* data = [[NSData alloc] initWithContentsOfURL:url]; UIImage* image = [[UIImage alloc] initWithData:data]; if (data != nil) { dispatch_async(dispatch_get_main_queue(), ^{ self.imageView.image = image; }); } }); }
GCD會自動根據任務在多核處理器上分配資源,優化程序。
系統給每一個應用程序提供了三個併發調度隊列(concurrent dispatch queues),這3個隊列是全局的,它們只有優先級的不一樣。由於是全局的,咱們不須要去建立,只須要經過使用函數 dispatch_get_global_queue 去獲得隊列。以下:
dispatch_queue_t globalQ = dispatch_get_global_queue(DISPATCH_QUEU_PRIORITY_DEFAULT, 0);
系統還提供了一個主調度隊列 main_queue
dispatch_queue_t mainQueue = dispatch_get_main_queue();
這些隊列都是全局隊列,,不用retain或release。
dispatch_group_async能夠實現監聽一組任務是否完成,完成後再通知執行其餘的操做。以下示例:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, queue, ^{ [NSThread sleepForTimeInterval:1]; NSLog(@"group1"); }); dispatch_group_async(group, queue, ^{ [NSThread sleepForTimeInterval:1]; NSLog(@"group2"); }); dispatch_group_async(group, queue, ^{ [NSThread sleepForTimeInterval:1]; NSLog(@"group3"); }); dispatch_group_notify(group, dispatch_get_main_queue(), ^{ NSLog(@"updateUI"); });
前3個dispatch_group_async執行是異步的,順序不定。
dispatch_barrier_async 是在前面的任務執行結束後它才執行,並且它後面的任務等它執行完成以後纔會執行。示例代碼:
dispatch_queue_t queue = dispatch_queue_create("gcdtest.rongfzh.yc", DISPATCH_QUEUE_CONCURRENT); dispatch_async(queue, ^{ [NSThread sleepForTimeInterval:1]; NSLog(@"dispatch_async1"); }); dispatch_async(queue, ^{ [NSThread sleepForTimeInterval:1]; NSLog(@"dispatch_async2"); }); dispatch_async(queue, ^{ [NSThread sleepForTimeInterval:1]; NSLog(@"dispatch_async3"); }); dispatch_barrier_async(queue, ^{ NSLog(@"dispatch_barrier_async"); [NSThread sleepForTimeInterval:4]; }); dispatch_async(queue, ^{ [NSThread sleepForTimeInterval:1]; NSLog(@"dispatch_async4"); });
一樣的,前3個dispatch_async執行是異步的,順序不定。
執行某個代碼片斷N次。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_apply(5, queue, ^(size_t index) { NSLog(@"dispatch_apply: index: %d", index); });
GCD還有不少其餘用法,能夠參考官方文檔