1. 程式人生 > >iOS —— 關於GCD的理解和使用

iOS —— 關於GCD的理解和使用

central 同時 註意 執行 理解 current 線程管理 null 字符

一.什麽是GCD

Grand Central Dispatch (強大的中樞調度器) ,是異步執行任務的技術之一。純C語言,有很多強大的函數。

二.GCD的優勢

(1)GCD是蘋果公司為多核並行運算提供的解決方案。

(2)GCD會自動利用更多的CPU內核(雙核,四核等)。

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

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

三.任務和隊列

  GCD中有兩個很核心的概念:任務和隊列。

  任務:你要執行的操作

隊列:用來存放任務

四.執行任務的兩種方式

1.同步:在當前線程中執行

  異步:在另一個線程中執行

  2. GCD中有兩個用來執行任務的函數:

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

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

五.隊列的兩種類型

  (1) 串行隊列:在一個線程中依次執行(dispatch_sync)

     並發隊列:多個任務同時執行 (開啟多個線程同時執行任務)(dispatch_async)

(2)同步、異步、串行、並發 說明

     同步和異步決定了能不能開啟新線程

     同步:在當前線程中執行任務,不具備開啟新線程的能力

     異步:在新的線程中執行任務,具備開啟新線程的能力  

    串行和並行決定了任務的執行形式

    串行:任務依次執行

    並行:多個任務同時並發執行

   註意:只有在異步的時候開啟線程,所以只能在異步的時候並發執行任務。

六.獲取隊列的函數

1獲取串行隊列

(1)使用dispatch_queue_create函數創建串行隊列

dispatch_queue_t queue = dispatch_queue_create("
wendingding", NULL); // 創建

(2)使用主隊列(跟主線程相關聯的隊列)

dispatch_queue_t queue = dispatch_get_main_queue();

2.獲取並行隊列

使用dispatch_get_global_queue函數獲得全局的並發隊列

dispatch_queue_t dispatch_get_global_queue(dispatch_queue_priority_t priority,unsigned long flags); // 此參數暫時無用,用0即可

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // 獲得全局並發隊列

說明:全局並發隊列的優先級

#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 // 後臺

七、GCD的基本使用

1. 串行隊列 + 同步執行

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"主線程----%@",[NSThread mainThread]);
    
    //創建串行隊列
    dispatch_queue_t queue = dispatch_queue_create("dengdeng", 0);
    
    //添加任務到隊列中去
    dispatch_sync(queue, ^{
        NSLog(@"下載圖片1 ----- %@",[NSThread currentThread]);
    });
    
    dispatch_sync(queue, ^{
        NSLog(@"下載圖片2 ----- %@",[NSThread currentThread]);
    });
    
    dispatch_sync(queue, ^{
        NSLog(@"下載圖片3 ----- %@",[NSThread currentThread]);
    });
    
    
}

打印結果如下:

2017-06-16 16:56:16.331 GCDTest[14678:2213850] 主線程----<NSThread: 0x608000073000>{number = 1, name = main}

2017-06-16 16:56:16.332 GCDTest[14678:2213850] 下載圖片1 ----- <NSThread: 0x608000073000>{number = 1, name = main}

2017-06-16 16:56:16.333 GCDTest[14678:2213850] 下載圖片2 ----- <NSThread: 0x608000073000>{number = 1, name = main}

2017-06-16 16:56:16.333 GCDTest[14678:2213850] 下載圖片3 ----- <NSThread: 0x608000073000>{number = 1, name = main}

2. 並行隊列 + 同步執行

- (void)viewDidLoad

{

[super viewDidLoad];

NSLog(@"主線程----%@",[NSThread mainThread]);

//創建串行隊列

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

//第一個參數為串行隊列的名稱,是c語言的字符串

//第二個參數為隊列的屬性,一般來說串行隊列不需要賦值任何屬性,所以通常傳空值(NULL)

//添加任務到隊列中去

dispatch_sync(queue, ^{

for (int i = 0; i < 2 ; i ++) {

NSLog(@"下載圖片1 ----- %@",[NSThread currentThread]);

}

});

dispatch_sync(queue, ^{

for (int i = 0; i < 2 ; i ++) {

NSLog(@"下載圖片2 ----- %@",[NSThread currentThread]);

}

});

dispatch_sync(queue, ^{

for (int i = 0; i < 2 ; i ++) {

NSLog(@"下載圖片3 ----- %@",[NSThread currentThread]);

}

});

}

打印結果:

2017-06-16 17:29:58.848 GCDTest[14951:2249589] 主線程----<NSThread: 0x600000068600>{number = 1, name = main}

2017-06-16 17:29:58.849 GCDTest[14951:2249589] 下載圖片1 ----- <NSThread: 0x600000068600>{number = 1, name = main}

2017-06-16 17:29:58.849 GCDTest[14951:2249589] 下載圖片1 ----- <NSThread: 0x600000068600>{number = 1, name = main}

2017-06-16 17:29:58.849 GCDTest[14951:2249589] 下載圖片2 ----- <NSThread: 0x600000068600>{number = 1, name = main}

2017-06-16 17:29:58.849 GCDTest[14951:2249589] 下載圖片2 ----- <NSThread: 0x600000068600>{number = 1, name = main}

2017-06-16 17:29:58.849 GCDTest[14951:2249589] 下載圖片3 ----- <NSThread: 0x600000068600>{number = 1, name = main}

2017-06-16 17:29:58.849 GCDTest[14951:2249589] 下載圖片3 ----- <NSThread: 0x600000068600>{number = 1, name = main}

註:同步執行不會開啟新線程

2. 串行隊列 + 異步執行

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"主線程----%@",[NSThread mainThread]);
    //創建串行隊列
    dispatch_queue_t queue = dispatch_queue_create("dengdeng", 0);
    //第一個參數為串行隊列的名稱,是c語言的字符串
    //第二個參數為隊列的屬性,一般來說串行隊列不需要賦值任何屬性,所以通常傳空值(NULL)

    //添加任務到隊列中去
    dispatch_async(queue, ^{
        NSLog(@"下載圖片1 ----- %@",[NSThread currentThread]);
    });
    
    dispatch_async(queue, ^{
        NSLog(@"下載圖片2 ----- %@",[NSThread currentThread]);
    });
    
    dispatch_async(queue, ^{
        NSLog(@"下載圖片3 ----- %@",[NSThread currentThread]);
    });
    
}

2017-06-16 17:15:09.901 GCDTest[14851:2235809] 主線程----<NSThread: 0x60800007ad80>{number = 1, name = main}

2017-06-16 17:15:09.901 GCDTest[14851:2235848] 下載圖片1 ----- <NSThread: 0x608000262c40>{number = 3, name = (null)}

2017-06-16 17:15:09.901 GCDTest[14851:2235848] 下載圖片2 ----- <NSThread: 0x608000262c40>{number = 3, name = (null)}

2017-06-16 17:15:09.902 GCDTest[14851:2235848] 下載圖片3 ----- <NSThread: 0x608000262c40>{number = 3, name = (null)}

註:開啟了新的線程,在新的線程上,這三個任務是串行的。

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"主線程----%@",[NSThread mainThread]);
    
    //創建串行隊列
    dispatch_queue_t queue = dispatch_queue_create("dengdeng", 0);
    //第一個參數為串行隊列的名稱,是c語言的字符串
    //第二個參數為隊列的屬性,一般來說串行隊列不需要賦值任何屬性,所以通常傳空值(NULL)
    //添加任務到隊列中去
    dispatch_async(queue, ^{
        NSLog(@"下載圖片1 ----- %@",[NSThread currentThread]);
    });
    
    dispatch_async(queue, ^{
        NSLog(@"下載圖片2 ----- %@",[NSThread currentThread]);
    });
    
    dispatch_async(queue, ^{
        NSLog(@"下載圖片3 ----- %@",[NSThread currentThread]);
    });
    
    for (int i = 0; i < 3 ; i ++) {
        NSLog(@"下載圖片main ----- %@",[NSThread currentThread]);
    }

}

2017-06-16 17:19:06.154 GCDTest[14870:2240144] 主線程----<NSThread: 0x60800007d200>{number = 1, name = main}

2017-06-16 17:19:06.155 GCDTest[14870:2240144] 下載圖片main ----- <NSThread: 0x60800007d200>{number = 1, name = main}

2017-06-16 17:19:06.155 GCDTest[14870:2240278] 下載圖片1 ----- <NSThread: 0x600000268400>{number = 3, name = (null)}

2017-06-16 17:19:06.155 GCDTest[14870:2240144] 下載圖片main ----- <NSThread: 0x60800007d200>{number = 1, name = main}

2017-06-16 17:19:06.155 GCDTest[14870:2240278] 下載圖片2 ----- <NSThread: 0x600000268400>{number = 3, name = (null)}

2017-06-16 17:19:06.155 GCDTest[14870:2240144] 下載圖片main ----- <NSThread: 0x60800007d200>{number = 1, name = main}

2017-06-16 17:19:06.155 GCDTest[14870:2240278] 下載圖片3 ----- <NSThread: 0x600000268400>{number = 3, name = (null)}

註:開啟的新線程和主線程的關系:並發執行

4. 並行隊列 + 異步執行

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"主線程----%@",[NSThread mainThread]);
    
    //創建串行隊列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    //第一個參數為串行隊列的名稱,是c語言的字符串
    //第二個參數為隊列的屬性,一般來說串行隊列不需要賦值任何屬性,所以通常傳空值(NULL)
    //添加任務到隊列中去
    dispatch_async(queue, ^{
        for (int i = 0; i < 3 ; i ++) {
            NSLog(@"下載圖片1 ----- %@",[NSThread currentThread]);
        }
    });
    
    dispatch_async(queue, ^{
        for (int i = 0; i < 3 ; i ++) {
            NSLog(@"下載圖片2 ----- %@",[NSThread currentThread]);
        }
    });
    
    

}

2017-06-16 17:25:40.722 GCDTest[14920:2245705] 主線程----<NSThread: 0x60000007f240>{number = 1, name = main}

2017-06-16 17:25:40.725 GCDTest[14920:2245740] 下載圖片1 ----- <NSThread: 0x60000026b9c0>{number = 3, name = (null)}

2017-06-16 17:25:40.725 GCDTest[14920:2245742] 下載圖片2 ----- <NSThread: 0x608000264b00>{number = 4, name = (null)}

2017-06-16 17:25:40.752 GCDTest[14920:2245740] 下載圖片1 ----- <NSThread: 0x60000026b9c0>{number = 3, name = (null)}

2017-06-16 17:25:40.753 GCDTest[14920:2245742] 下載圖片2 ----- <NSThread: 0x608000264b00>{number = 4, name = (null)}

2017-06-16 17:25:40.755 GCDTest[14920:2245740] 下載圖片1 ----- <NSThread: 0x60000026b9c0>{number = 3, name = (null)}

2017-06-16 17:25:40.756 GCDTest[14920:2245742] 下載圖片2 ----- <NSThread: 0x608000264b00>{number = 4, name = (null)}

註:開啟多個線程,並發執行任務

iOS —— 關於GCD的理解和使用