你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> iOS-多線程之GCD

iOS-多線程之GCD

編輯:IOS開發綜合

在說GCD之前,先說幾個核心的概念

任務:執行什麼操作
隊列:用來存放任務

1 - 並發隊列(Concurrent Dispatch Queue) 可以讓多個任務並發(同時)執行(自動開啟多個線程同時執行任務) 並發功能只有在異步(dispatch_async)函數下才有效

2 - 串行隊列(Serial Dispatch Queue) 讓任務一個接著一個地執行(一個任務執行完畢後,再執行下一個任務)


同步和異步的區別

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


GCD使用步驟

一、創建任務

二、將任務添加到隊列中
GCD會自動將隊列中的任務取出,放到對應的線程中執行
任務的取出遵循隊列的FIFO原則:先進先出,後進後出


GCD線程隊列的創建方法

1、創建一個串行隊列

    /**
     *  創建一個串行隊列
     *
     *  @param "Mazy"                    隊列的標示符
     *  @param DISPATCH_QUEUE_SERIAL     串行隊列
               DISPATCH_QUEUE_CONCURRENT 並發隊列
     *
     *  @return 返回串行隊列
     */
    dispatch_queue_t serialQueue = dispatch_queue_create("Mazy", DISPATCH_QUEUE_SERIAL);

2、創建一個並發隊列

/**
     *  創建一個並發隊列
     *
     *  @param "Mazy"                    隊列的標示符
     *  @param DISPATCH_QUEUE_CONCURRENT 並發隊列
     *
     *  @return 返回並發隊列
     */
    dispatch_queue_t concurrentQueue = dispatch_queue_create("Mazy", DISPATCH_QUEUE_CONCURRENT);

3、獲得全局並發隊列

/**
     *  獲得全局並發隊列
     *
     *  @param DISPATCH_QUEUE_PRIORITY_DEFAULT 線程隊列的優先級

               DISPATCH_QUEUE_PRIORITY_HIGH 2     高
               DISPATCH_QUEUE_PRIORITY_DEFAULT 0  一般 默認
               DISPATCH_QUEUE_PRIORITY_LOW (-2)   低
               DISPATCH_QUEUE_PRIORITY_BACKGROUND 很低

     *  @param 0                               系統保留參數
     *
     *  @return 返回全局並發隊列
     */
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

3、獲得主隊列

/**
     *  獲得主隊列
     *
     *  @return 返回主線程隊列
     */
    dispatch_queue_t mainQueue = dispatch_get_main_queue();

同步/異步 + 串行/並發隊列的組合

1、同步 + 串行隊列

// 同步 + 串行隊列:不會開啟新的線程,在當前線程執行任務。任務是串行的,執行完一個任務,再執行下一個任務
-(void)sync_serial {
    // 創建一個串行隊列
    dispatch_queue_t queue = dispatch_queue_create("Mazy", DISPATCH_QUEUE_SERIAL);
    // 同步執行三個任務
    dispatch_sync(queue, ^{
        NSLog(@"1 %@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"2 %@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"3 %@",[NSThread currentThread]);
    });
}

打印結果:

這裡寫圖片描述

總結:沒有創建新線程,主線程執行任務,任務串行執行


2、異步 + 串行隊列

// 異步 + 串行隊列:開啟新的線程,但只開啟一條
-(void)async_serial {
    // 創建一個串行隊列
    dispatch_queue_t queue = dispatch_queue_create("Mazy", DISPATCH_QUEUE_SERIAL);
    // 異步執行三個任務
    dispatch_async(queue, ^{
        NSLog(@"1 %@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"2 %@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"3 %@",[NSThread currentThread]);
    });
}

打印結果:

這裡寫圖片描述

總結:開啟了一條線程,任務串行執行


3、同步 + 並發隊列

// 同步 + 並發隊列:不會開啟新的線程
-(void)sync_concurrent {
    // 創建一個全局並發隊列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    // 同步執行三個任務
    dispatch_sync(queue, ^{
        NSLog(@"1 %@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"2 %@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"3 %@",[NSThread currentThread]);
    });
}

打印結果:

這裡寫圖片描述

總結:不開啟新線程,主線程執行任務,任務也是順序執行


4、異步 + 並發隊列

// 異步 + 並發隊列:同時開啟多條線程
-(void)async_concurrent {
    // 創建一個全局並發隊列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    // 異步執行三個任務
    dispatch_async(queue, ^{
        NSLog(@"1 %@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"2 %@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"3 %@",[NSThread currentThread]);
    });
}

打印結果:

這裡寫圖片描述

總結:開啟多條線程,並發執行任務


GCD線程之間的通信

從子線程回到主線程

從子線程回到主線程
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // 執行耗時的異步操作...
      dispatch_async(dispatch_get_main_queue(), ^{
        // 回到主線程,執行UI刷新操作
        });
});

線程之間的通信具體實現實例

    // 創建 異步 全局並發隊列
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // 圖片的網絡路徑
        NSURL *url = [NSURL URLWithString:@"http://xxx.jpg"];

        // 加載圖片
        NSData *data = [NSData dataWithContentsOfURL:url];

        // 生成圖片
        UIImage *image = [UIImage imageWithData:data];

        // 回到主線程設置圖片
        dispatch_async(dispatch_get_main_queue(), ^{
            self.imageView.image = image;
        });
    });

GCD的其他使用

延遲執行

/**
 *  延遲執行
 */
-(void)delay {
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"---我被延遲了3秒執行---");
    });
}

其他延遲執行方法

// method 1
[self performSelector:@selector(do_method) withObject:nil afterDelay:3.0];

// method 2
[NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(do_method) userInfo:nil repeats:NO];

只執行一次(用於實現單例模式)

/**
 *  只執行一次
 */
-(void)onlyOnce {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSLog(@"---我只會被執行一次---");
    });
}

快速遍歷

/**
 * 快速遍歷
 */
-(void)apply {
   // 創建一個全局並發隊列
   dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    NSInteger count = 10;
    dispatch_apply(count, queue, ^(size_t index) {
        NSLog(@"%zd--%@",index,[NSThread currentThread]);
    });
}

打印結果:

這裡寫圖片描述

總結:開啟多條線程執行任務,速度遠比(for…in…) 遍歷快,對於無序的遍歷,此方法比較合適


創建線程群組
例如同一個文件分段下載,待所有分段任務下載完成後,合並任務

/**
 *  創建線程群組
 */
-(void)group {
    // 創建一個全局並發隊列
    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, ^{
        NSLog(@"我是任務-1 %@",[NSThread currentThread]);
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"我是任務-2 %@",[NSThread currentThread]);
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"我是任務-3 %@",[NSThread currentThread]);
    });

    // 待群組中的每個任務執行完成後,執行此方法
    dispatch_group_notify(group, queue, ^{
        NSLog(@"我是終極任務,只有在group裡面的任務執行完畢後才執行");
        NSLog(@"%@",[NSThread currentThread]);

    });
}

打印結果:

這裡寫圖片描述

總結:開啟多條線程,去執行群組中的任務,當群組內的三個任務執行完畢後,再去執行notify裡面的任務


創建屏障線程隊列

/**
 * 創建屏障線程隊列
 */
-(void)barrier {
    // 創建一個並發隊列
    dispatch_queue_t queue = dispatch_queue_create("Mazy", DISPATCH_QUEUE_CONCURRENT);
    // 創建四個異步任務
    dispatch_async(queue, ^{
        NSLog(@"我是任務-1 %@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"我是任務-2 %@",[NSThread currentThread]);
    });

    // 創建屏障線程隊列
    dispatch_barrier_async(queue, ^{
        NSLog(@"----barrier-----%@", [NSThread currentThread]);
    });

    dispatch_async(queue, ^{
        NSLog(@"我是任務-3 %@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"我是任務-4 %@",[NSThread currentThread]);
    });
}

打印結果:

這裡寫圖片描述

總結:會優先執行屏障前面的任務,當屏障前的所有任務執行完畢後,再去執行後面的任務


注意:使用sync同步函數往當前串行隊列中添加任務,會卡住當前的串行隊列
  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved