iOS開發多線程---GCD的介紹和簡單使用

jopen 9年前發布 | 45K 次閱讀 IOS iOS開發 移動開發

GCD的工作原理是:讓程序平行排隊的特定任務,根據可用的處理資源,安排他們在任何可用的處理器核心上執行任務。一個任務可以是一個函數(function)或者是一個block。 GCD的底層依然是用線程實現,不過這樣可以讓程序員不用關注實現的細節。GCD中的FIFO隊列稱為dispatch queue,它可以保證先進來的任務先得到執行。用gcd實現網絡數據請求,比前面介紹的NSThread方法要簡單的多。

1.GCD的簡介:

 Grand Central Dispatch 簡稱(GCD)是蘋果公司開發的技術,以優化的應用程序支持多核心處理器和其他的對稱多處理系統的系統。這建立在任務并行執行的線程池模式的基礎上的。而且是純C語言,提供了非常多強大的函數。

2.GCD的工作原理是:

讓程序平行排隊的特定任務,根據可用的處理資源,安排他們在任何可用的處理器核心上執行任務。一個任務可以是一個函數(function)或者是一個block。 GCD的底層依然是用線程實現,不過這樣可以讓程序員不用關注實現的細節。

3.GCD的優勢:

GCD是蘋果公司為多核的并行運算提出的解決方案;

GCD會自動利用更多的CPU內核(比如雙核、四核);

GCD會自動管理線程的生命周期(創建線程、調度任務、銷毀線程);

程序員只需要告訴GCD想要執行什么任務,不需要編寫任何線程管理代碼;

溫馨提示:

GCD存在于libdispatch.dylib這個庫中,這個調度庫包含了GCD的所有的東西,但任何IOS程序,默認就加載了這個庫,在程序運行的過程中會動態的加載這個庫,不需要我們手動導入。

4.GCD的使用步驟和核心概念:

核心概率有2個:1)隊列:用來存放任務  2)任務:執行什么操作

使用步驟有2步:1)定制任務 2)確定想做的事情

5.dispatch queue(隊列)

GCD中的FIFO隊列稱為dispatch queue,它可以保證先進來的任務先得到執行,dispatch queue分為下面三種:

1)Serial dispatch queues(串行隊列),同時只執行一個任務(一個任務執行完畢以后,再執行下一個任務)。Serial queue通常用于同步訪問特定的資源或數據。當你創建多個Serial queue時,雖然它們各自是同步執行的,但Serial queue與Serial queue之間是并發執行的。

2)Concurren dispatch queue(并發隊列),可以并發地執行多個任務(可以讓多個任務同時執行,自動開啟多個線程同時執行任務,并發功能只有在異步函數(dispatch_async)下有效),但是執行完成的順序是隨機的。

3)Main dispatch queue(主隊列),它是全局可用的serial queue(直接在主線程中串行執行任務),它是在應用程序主線程上執行任務的。

6.GCD執行任務的兩種方式:

//將參數block(任務)提交給參數queue(隊列)進行執行,參數說明:queue:隊列   block:任務

(1)用同步的方式執行任務 dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);

(2)用異步的方式執行任務 dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

7.為了避免界面在處理耗時的操作時卡死,比如讀取網絡數據,數據庫讀寫等,我們會在另外一個線程中處理這些操作,然后通知主線程更新界面。創建一個全局并發隊列,使用dispatch_async執行下載圖片任務,然后再回到主線程中展示圖片。

第一種方式---GCD結合NSThread

 - (void)viewDidLoad
{
    [super viewDidLoad];
 
    imagev = [[UIImageView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
    [self.view addSubview:imagev];
    
 //說明:全局并發隊列的優先級
#define DISPATCH_QUEUE_PRIORITY_HIGH 2 // 高
#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 // 默認(中)
#define DISPATCH_QUEUE_PRIORITY_LOW (-2) // 低
#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN // 后臺
    
    //第一個參數全局并發隊列的優先級,第二個參數暫時無用,用0即可
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    //使用異步的方式dispatch_async執行任務,第一個參數獲得全局的并發隊列,第二個參數block(隊列將要執行的任務)
    dispatch_async(queue, ^{
        //調用下載圖片方法
        [self downImage];
    });
}
-(void)downImage
{
    //從網絡中下載圖片
    NSURL *url = [NSURL URLWithString:@"http://i8.topit.me/8/c1/31/1142319854bdc31c18o.jpg"];
    //將圖片轉換為二進制數據
    NSData *imgData = [NSData dataWithContentsOfURL:url];
    //數據轉換成圖片
    UIImage *img = [UIImage imageWithData:imgData];
    
    //回到主線程設置圖片
    [self performSelectorOnMainThread:@selector(senderImage:) withObject:img waitUntilDone:NO];
}

-(void)senderImage:(UIImage *)image
{
    imagev.image = image;
}

第二種方式---GCD

   dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        
        //從網絡中下載圖片
        NSURL *url = [NSURL URLWithString:@"http://i8.topit.me/8/c1/31/1142319854bdc31c18o.jpg"];
        //將圖片轉換為二進制數據
        NSData *imgData = [NSData dataWithContentsOfURL:url];
        //數據轉換成圖片
        UIImage *img = [UIImage imageWithData:imgData];
        
        dispatch_async(dispatch_get_main_queue(), ^{
            //回到主線程中設置圖片顯示
            imagev.image = img;
        });
    });

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

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

上面的例子中我們也用到了,系統默認就有的一個串行隊列main_queue

dispatch_queue_t mainQueut = dispatch_get_main_queue();

他們的代碼框架結構如下:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{  
    //這里就做一些比較耗時的操作,如請求數據。。  
    dispatch_async(dispatch_get_main_queue(), ^{  
        //這里就是回到主線程去更新界面  
    });  
});


 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!