GCD

首先要肯定:一個線程只能執行一個任務,執行完纔會執行另外一個任務程序員

先總結一張圖網絡

同步和異步併發

dispatch_sync 是同步的方式執行任務
dispatch_async 是異步的方式執行任務
同步和異步的區別
同步:在當前線程中執行(不會開闢新線程,是在當前線程執行,通常使用同步執行任務會立馬執行,‘寫了跟沒寫同樣’)  
異步:在另外一條新的線程中執行(把任務放在主隊列裏,可是不須要立刻執行)異步

串行隊列和並行隊列async

串行隊列:一個一個執行,就算在異步執行的時候,也只會開闢一條新線程(若是主線程是數字是1,那串行隊列只會開闢出一個數字2的線程),而且全部的任務都會在新的線程中執行
dispatch_queue_t  queue = dispatch_queue_create(「label」, DISPATCH_QUEUE_SERIAL);
或者
dispatch_queue_t  queue = dispatch_queue_create(「label」, NULL);  這兩種的建立方式是同樣的 程序中會常常寫成NULL;
spa


並行隊列:在異步執行時會開闢不少新的線程,能夠同時執行多個任務,順序是程序員沒法控制的
dispatch_queue_t  queue = dispatch_queue_create(「label」, DISPATCH_QUEUE_CONCURRENT);
併發隊列的同步執行,不開闢新線程,一步一步執行任務
線程

GCD     主線程
1. 專門在主線程上調度任務
2. 不會開闢新線程,無論同步異步執行,只能在主線程上順序執行
code

主線程的異步執行任務blog

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [self gcdText5];
}

- (void)gcdText5
{
    // 1.得到主線程
    dispatch_queue_t queue = dispatch_get_main_queue();
    
    NSLog(@"1-------");
    
    // 2.異步執行任務
    // 把任務放在主隊列裏,可是不須要立刻執行
    for (int i = 0; i < 10; i++) {
        NSLog(@"調度前-----");
        // 任務:block
        dispatch_async(queue, ^{
            NSLog(@"%@, %d", [NSThread currentThread], i);
        });
        NSLog(@"睡會");
        [NSThread sleepForTimeInterval:2.0];
    }
    
    NSLog(@"完成");
    
}

這是運行順序是以下圖隊列

2016-05-29 17:09:24.945 GCD[6702:82350] 1-------
2016-05-29 17:09:24.946 GCD[6702:82350] 調度前-----
2016-05-29 17:09:24.946 GCD[6702:82350] 睡會
2016-05-29 17:09:26.951 GCD[6702:82350] 調度前-----
2016-05-29 17:09:26.951 GCD[6702:82350] 睡會
2016-05-29 17:09:28.954 GCD[6702:82350] 調度前-----
2016-05-29 17:09:28.954 GCD[6702:82350] 睡會
2016-05-29 17:09:30.959 GCD[6702:82350] 調度前-----
2016-05-29 17:09:30.959 GCD[6702:82350] 睡會
2016-05-29 17:09:32.963 GCD[6702:82350] 調度前-----
2016-05-29 17:09:32.964 GCD[6702:82350] 睡會
2016-05-29 17:09:34.969 GCD[6702:82350] 調度前-----
2016-05-29 17:09:34.969 GCD[6702:82350] 睡會
2016-05-29 17:09:36.971 GCD[6702:82350] 調度前-----
2016-05-29 17:09:36.971 GCD[6702:82350] 睡會
2016-05-29 17:09:38.971 GCD[6702:82350] 調度前-----
2016-05-29 17:09:38.971 GCD[6702:82350] 睡會
2016-05-29 17:09:40.974 GCD[6702:82350] 調度前-----
2016-05-29 17:09:40.974 GCD[6702:82350] 睡會
2016-05-29 17:09:42.977 GCD[6702:82350] 調度前-----
2016-05-29 17:09:42.977 GCD[6702:82350] 睡會
2016-05-29 17:09:44.981 GCD[6702:82350] 完成
2016-05-29 17:09:44.981 GCD[6702:82350] <NSThread: 0x7ffddb501290>{number = 1, name = main}, 0
2016-05-29 17:09:44.982 GCD[6702:82350] <NSThread: 0x7ffddb501290>{number = 1, name = main}, 1
2016-05-29 17:09:44.982 GCD[6702:82350] <NSThread: 0x7ffddb501290>{number = 1, name = main}, 2
2016-05-29 17:09:44.982 GCD[6702:82350] <NSThread: 0x7ffddb501290>{number = 1, name = main}, 3
2016-05-29 17:09:44.982 GCD[6702:82350] <NSThread: 0x7ffddb501290>{number = 1, name = main}, 4
2016-05-29 17:09:44.982 GCD[6702:82350] <NSThread: 0x7ffddb501290>{number = 1, name = main}, 5
2016-05-29 17:09:44.983 GCD[6702:82350] <NSThread: 0x7ffddb501290>{number = 1, name = main}, 6
2016-05-29 17:09:44.983 GCD[6702:82350] <NSThread: 0x7ffddb501290>{number = 1, name = main}, 7
2016-05-29 17:09:44.983 GCD[6702:82350] <NSThread: 0x7ffddb501290>{number = 1, name = main}, 8
2016-05-29 17:09:44.983 GCD[6702:82350] <NSThread: 0x7ffddb501290>{number = 1, name = main}, 9

爲何會產生這種效果呢

由於異步執行只是把任務放在隊列中,不會立刻執行,由於主隊列的特殊性又不能開闢新的線程,因此會等到主線程的任務執行完纔會執行隊列中的任務 , 如圖

此時主線程正在執行gcdText5這個任務,

當gocText5任務執行完成後在執行  綠色的0,1任務

 

主線程的同步執行任務

只須要將代碼

 dispatch_async

 

換成

 dispatch_sync

就能夠了,這是運行效果回事這樣的

這是由於

 同步任務要立刻執行,可是線程沒空,線程正在執行gcdText5,須要等gcdText5執行完,可是gcdText5在等這個同步任務執行結束,因此會形成主線程阻塞,產生死鎖

全局隊列

全局隊列和併發隊列的區別
 1.全局隊列沒有名稱,併發隊列有名稱
 2.全局隊列,是供全部的應用程序共享
 3.在MRC開發中併發隊列須要釋放,全局隊列不須要管理

 

// 全局隊列:是蘋果官方提供的,是指上也是併發隊列
    /*
     參數:第一個參數,通常寫 0 (能夠適配iOS 7 & 8)
(優先級)DISPATCH_QUEUE_PRIORITY_HIGH:         QOS_CLASS_USER_INITIATED
   (0) DISPATCH_QUEUE_PRIORITY_DEFAULT:      QOS_CLASS_DEFAULT
       DISPATCH_QUEUE_PRIORITY_LOW:          QOS_CLASS_UTILITY
       DISPATCH_QUEUE_PRIORITY_BACKGROUND:   QOS_CLASS_BACKGROUND
          第二個參數:保留參數  0
     **/
    
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    
    for (int i = 0; i < 10; i ++) {
        dispatch_async(queue, ^{
            NSLog(@"%@, %d", [NSThread currentThread], i);
        });
    }

 

調度組

/*
    應用場景
    開發的時候出現多個網絡請求(每個網絡請求的時間長短不必定),都完成之後,在統一通知用戶
    
    例如:下載小說:三國演義 西遊記 金x梅
    **/
    
    // 實例化一個調度組
    dispatch_group_t group = dispatch_group_create();
    
    // 隊列
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);

    // 任務添加到隊列
    dispatch_group_async(group, queue, ^{
        NSLog(@"下載小說A%@", [NSThread currentThread]);
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"下載小說b%@", [NSThread currentThread]);
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"下載小說x%@", [NSThread currentThread]);
    });
    
    // 得到全部調度組裏面的異步任務完成的通知(能夠跨隊列通訊)
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        // 在主線程更新UI
        NSLog(@"下載完成,請觀看%@", [NSThread currentThread]);
    });

一次性執行   

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [self once];
}

#pragma mark - 一次性執行
- (void)once
{
    static dispatch_once_t onceToken;
    
    NSLog(@"%ld", onceToken);
    
    dispatch_once(&onceToken, ^{
        
        NSLog(@"%ld", onceToken);
        NSLog(@"真的只會執行一次麼?");
    });
    
    NSLog(@"完成");
}

運行結果

2016-05-30 17:34:57.939 GCD[29725:464402] 0
2016-05-30 17:34:57.940 GCD[29725:464402] 140734769974144
2016-05-30 17:34:57.940 GCD[29725:464402] 真的只會執行一次麼?
2016-05-30 17:34:57.940 GCD[29725:464402] 完成
2016-05-30 17:34:59.898 GCD[29725:464402] -1
2016-05-30 17:34:59.898 GCD[29725:464402] 完成
2016-05-30 17:35:00.690 GCD[29725:464402] -1
2016-05-30 17:35:00.690 GCD[29725:464402] 完成
2016-05-30 17:35:01.090 GCD[29725:464402] -1
2016-05-30 17:35:01.091 GCD[29725:464402] 完成
2016-05-30 17:35:02.146 GCD[29725:464402] -1
2016-05-30 17:35:02.147 GCD[29725:464402] 完成
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息