GCD簡單使用

隊列類型

并發隊列(Concurrent Dispatch Queue)任務并發(同步)執行
串行隊列(Serial Dispatch Queue)任務順序執行
全局隊列(Global Queue)并發隊列
主隊列(Main Queue)串行隊列
    /**
     *  lable : 隊列名稱
     *  attr : 隊列類型,并發(ConCurrent),串行(Serial 或 NULL)
     */
    dispatch_queue_t conCurrentQueue = dispatch_queue_create("conCurrent", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_queue_t serialQueue = dispatch_queue_create("serial", DISPATCH_QUEUE_SERIAL);
    
    dispatch_queue_t serialQueue1 = dispatch_queue_create("serial1", NULL);

    /**
     *  全局并發隊列
     *  identifier : 優先級
     *  flags      : 設置為0即可
     */
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    /**
     *  主隊列,串行隊列
     */
    dispatch_queue_t mainQueue = dispatch_get_main_queue();

執行方式

同步執行-在當前線程執行
異步執行-在新線程執行
queue:隊列
block:任務,需要進行的操作
    //同步任務
    dispatch_sync(<#dispatch_queue_t queue#>, <#^(void)block#>)
    //異步任務
    dispatch_async(<#dispatch_queue_t queue#>, <#^(void)block#>)

代碼示例

  • 異步任務 + 串行隊列

開啟新線程,串行執行任務。

dispatch_queue_t serialCurrentQueue = dispatch_queue_create("myQueue", NULL);
    dispatch_async(serialCurrentQueue, ^{
        NSLog(@"串行隊列-異步任務1-%@", [NSThread currentThread]);
    });
    dispatch_async(serialCurrentQueue, ^{
        NSLog(@"串行隊列-異步任務2-%@", [NSThread currentThread]);
    });
    dispatch_async(serialCurrentQueue, ^{
        NSLog(@"串行隊列-異步任務3-%@", [NSThread currentThread]);
    });
    dispatch_async(serialCurrentQueue, ^{
        NSLog(@"串行隊列-異步任務4-%@", [NSThread currentThread]);
    });
    
    NSLog(@"執行完成");
    /*
     執行完成
     串行隊列-異步任務1-<NSThread: 0x7f9f32e1de80>{number = 2, name = (null)}
     串行隊列-異步任務2-<NSThread: 0x7f9f32e1de80>{number = 2, name = (null)}
     串行隊列-異步任務3-<NSThread: 0x7f9f32e1de80>{number = 2, name = (null)}
     串行隊列-異步任務4-<NSThread: 0x7f9f32e1de80>{number = 2, name = (null)}
     */
  • 異步任務 + 并行隊列

開啟新線程,同步執行任務。

dispatch_queue_t conCurrentQueue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(conCurrentQueue, ^{
        NSLog(@"并發隊列-異步任務1-%@", [NSThread currentThread]);
    });
    dispatch_async(conCurrentQueue, ^{
        NSLog(@"并發隊列-異步任務2-%@", [NSThread currentThread]);
    });
    dispatch_async(conCurrentQueue, ^{
        NSLog(@"并發隊列-異步任務3-%@", [NSThread currentThread]);
    });
    dispatch_async(conCurrentQueue, ^{
        NSLog(@"并發隊列-異步任務4-%@", [NSThread currentThread]);
    });
    
    NSLog(@"執行完成");
    /*
     執行完成
     并發隊列-異步任務1-<NSThread: 0x7fb751e1a6a0>{number = 5, name = (null)}
     并發隊列-異步任務3-<NSThread: 0x7fb751d08830>{number = 6, name = (null)}
     并發隊列-異步任務2-<NSThread: 0x7fb751d0ee50>{number = 2, name = (null)}
     并發隊列-異步任務4-<NSThread: 0x7fb751d0f340>{number = 4, name = (null)}
     
     或
     
     并發隊列-異步任務2-<NSThread: 0x7fb751d01d20>{number = 10, name = (null)}
     執行完成
     并發隊列-異步任務1-<NSThread: 0x7fb751d06210>{number = 9, name = (null)}
     并發隊列-異步任務3-<NSThread: 0x7fb751d0f400>{number = 11, name = (null)}
     并發隊列-異步任務4-<NSThread: 0x7fb751d08830>{number = 8, name = (null)}
     */
  • 異步任務 + 主線程

不開啟新線程,在主線程串行執行任務。

dispatch_queue_t mainQueue = dispatch_get_main_queue();
    dispatch_async(mainQueue, ^{
        NSLog(@"主隊列-異步任務1-%@", [NSThread currentThread]);
    });
    dispatch_async(mainQueue, ^{
        NSLog(@"主隊列-異步任務2-%@", [NSThread currentThread]);
    });
    dispatch_async(mainQueue, ^{
        NSLog(@"主隊列-異步任務3-%@", [NSThread currentThread]);
    });
    dispatch_async(mainQueue, ^{
        NSLog(@"主隊列-異步任務4-%@", [NSThread currentThread]);
    });
    
    NSLog(@"執行完成");
    /*
     執行完成
     主隊列-異步任務1-<NSThread: 0x7f8ccb601ec0>{number = 1, name = main}
     主隊列-異步任務2-<NSThread: 0x7f8ccb601ec0>{number = 1, name = main}
     主隊列-異步任務3-<NSThread: 0x7f8ccb601ec0>{number = 1, name = main}
     主隊列-異步任務4-<NSThread: 0x7f8ccb601ec0>{number = 1, name = main}
     */
  • 同步任務 + 串行隊列

不開啟新線程,串行執行任務。

dispatch_queue_t serialCurrentQueue = dispatch_queue_create("myQueue", NULL);
    
    dispatch_sync(serialCurrentQueue, ^{
        NSLog(@"串行隊列-同步任務1-%@", [NSThread currentThread]);
    });
    dispatch_sync(serialCurrentQueue, ^{
        NSLog(@"串行隊列-同步任務2-%@", [NSThread currentThread]);
    });
    dispatch_sync(serialCurrentQueue, ^{
        NSLog(@"串行隊列-同步任務3-%@", [NSThread currentThread]);
    });
    dispatch_sync(serialCurrentQueue, ^{
        NSLog(@"串行隊列-同步任務4-%@", [NSThread currentThread]);
    });
    
    NSLog(@"執行完成");
    /*
     串行隊列-同步任務1-<NSThread: 0x7f99c8600190>{number = 1, name = main}
     串行隊列-同步任務2-<NSThread: 0x7f99c8600190>{number = 1, name = main}
     串行隊列-同步任務3-<NSThread: 0x7f99c8600190>{number = 1, name = main}
     串行隊列-同步任務4-<NSThread: 0x7f99c8600190>{number = 1, name = main}
     執行完成
     */
  • 同步任務 + 并行隊列

不開啟新線程,串行執行任務。

dispatch_queue_t conCurrentQueue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_sync(conCurrentQueue, ^{
        NSLog(@"并發隊列-同步任務1-%@", [NSThread currentThread]);
    });
    dispatch_sync(conCurrentQueue, ^{
        NSLog(@"并發隊列-同步任務2-%@", [NSThread currentThread]);
    });
    dispatch_sync(conCurrentQueue, ^{
        NSLog(@"并發隊列-同步任務3-%@", [NSThread currentThread]);
    });
    dispatch_sync(conCurrentQueue, ^{
        NSLog(@"并發隊列-同步任務4-%@", [NSThread currentThread]);
    });
    
    NSLog(@"執行完成");
    /*
     并發隊列-同步任務1-<NSThread: 0x7fc1d2d08820>{number = 1, name = main}
     并發隊列-同步任務2-<NSThread: 0x7fc1d2d08820>{number = 1, name = main}
     并發隊列-同步任務3-<NSThread: 0x7fc1d2d08820>{number = 1, name = main}
     并發隊列-同步任務4-<NSThread: 0x7fc1d2d08820>{number = 1, name = main}
     執行完成
     */
  • 同步任務 + 主隊列

阻塞主線程

dispatch_queue_t mainQueue = dispatch_get_main_queue();
    NSLog(@"任務開始");
    dispatch_sync(mainQueue, ^{
        NSLog(@"主隊列-同步任務1-%@", [NSThread currentThread]);
    });
    NSLog(@"執行完成");
     /*主隊列等待同步任務完成,同步任務等待主隊列執行完,相互等待,誰都完成不了。
     任務開始
     */

表格總結

全局、并發隊列 自建串行隊列 主隊列
同步任務 不開啟新線程;串行執行任務 不開啟新線程;串行執行任務 造成死鎖
異步任務 開啟新線程;并發執行任務 開啟新線程;串行執行任務 不開啟新線程;串行執行任務


GCD調度組(線程組)

異步執行多個任務,當所有任務執行完成后,再執行某個任務。

代碼示例

GCD線程間通訊

主隊列=主線程=UI線程,所有的界面刷新都需要在主線程進行,子線程完成操作后,拿到主線程,在主線程進行刷新界面。

dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    
    dispatch_async(queue, ^{
        //執行耗時任務
        //...
       
        dispatch_async(dispatch_get_main_queue(), ^{
            //在主線程進行界面刷新
            //...
        });
    });

GCD延時函數

//第一種
    [self performSelector:@selector(showMessage) withObject:nil afterDelay:2.0f];
    
    //第二種
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        //2秒后執行的操作
        //...
    });

GCD執行一次函數

提示方法
static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        //只需要執行一次的代碼
        //...
    });

GCD柵欄函數

在并發隊列插入柵欄函數,會先執行柵欄函數之前的操作,再執行柵欄函數,最后執行柵欄函數后面的操作,起到柵欄的作用。

dispatch_queue_t queue = dispatch_queue_create("name", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(queue, ^{
        NSLog(@"耗時操作1-%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"耗時操作2-%@", [NSThread currentThread]);
    });
    
    dispatch_barrier_async(queue, ^{
        NSLog(@"柵欄函數-%@", [NSThread currentThread]);
    });
    
    dispatch_async(queue, ^{
        NSLog(@"耗時操作3-%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"耗時操作4-%@", [NSThread currentThread]);
    });
    
    NSLog(@"執行完成");
    /*
     執行完成
     耗時操作2-<NSThread: 0x7ff4b2dad620>{number = 2, name = (null)}
     耗時操作1-<NSThread: 0x7ff4b2c04bc0>{number = 3, name = (null)}
     柵欄函數-<NSThread: 0x7ff4b2c04bc0>{number = 3, name = (null)}
     耗時操作4-<NSThread: 0x7ff4b2dad620>{number = 2, name = (null)}
     耗時操作3-<NSThread: 0x7ff4b2c04bc0>{number = 3, name = (null)}
     */

GCD-dispatch_apply()函數

提交任務到隊列中多次執行,由隊列決定并行還是串行。dispatch_apply為同步任務,執行完dispatch_apply才會執行下面的操作。

/*   iterations 執行的次數
     queue      提交到的隊列
     size_t     索引,需要自己指定一個參數
     block      執行的任務

     dispatch_apply(size_t iterations, dispatch_queue_t queue, <#^(size_t)block#>)
*/
    dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);
    
    dispatch_apply(4, globalQueue, ^(size_t index) {
       //執行的循環操作
        NSLog(@"次數%d-%@", index, [NSThread currentThread]);
        
    });
    NSLog(@"執行完成");
    /*
     次數0-<NSThread: 0x7f9da35020d0>{number = 1, name = main}
     次數1-<NSThread: 0x7f9da340be60>{number = 2, name = (null)}
     次數3-<NSThread: 0x7f9da3740740>{number = 4, name = (null)}
     次數2-<NSThread: 0x7f9da3608440>{number = 3, name = (null)}
     執行完成
     */

參考
多線程----GCD的基本使用
多線程----GCD的常用函數和單例模式

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容