GCD全解析

目錄

  1. 文字描述
  2. Dispatch Queue
  3. dispatch_sync&dispatch_async
  4. 創建的線程任務有四種執行方式
  5. Dispatch Group
  6. Dispatch Block
  7. dispatch_after
  8. dispatch_apply
  9. dispatch_once
  10. dispatch_barrier_async
  11. dispatch_set_target_queue

1. 文字描述

GCD英文全稱:Grand Central Dispatch 翻譯就是 宏大的中央調度,是蘋果開發的一種支持并行操作的機制,基于C語言,提供了非常多強大的函數

在了解GCD并使用之前,必須要掌握四個名詞:串行,并發,同步,異步

串行(Serial):

一個任務執行完, 再執行下一個任務

并發 (Concurrent):

多個任務同時執行(自動開啟多個線程),只有在異步函數下才有效

同步(Synchronous):

在當前線程中執行任務,不具備開啟新線程的能力
提交的任務在執行完成后才會返回
同步函數: dispatch_sync()

異步 (Asynchronous):

在新的線程中執行任務, 具備開啟線程的能力
在新線程中執行任務,具備開啟新線程的能力
提交的任務立刻返回,在后臺隊列中執行
異步函數: dispatch_async()


2.Dispatch Queue

Dispatch Queue是執行處理的等待隊列, 按照先進先出(FIFO, First-In-First-Out)的順序進行任務處理.
開發者將需要執行的任務添加到合適的Dispatch Queue中即可,Dispatch Queue會根據任務添加的順序先到先執行,其中有以下幾種隊列:

另外, 隊列分兩種, 一種是串行隊列(Serial Dispatch Queue), 一種是并行隊列(Concurrent Dispatch Queue).

Dispatch Queue的種類 說明
Serial Dispatch Queue 等待現在執行中處理結束
Concurrent Dispatch Queue 不等待現在執行中處理結束
//創建一個串行隊列
dispatch_queue_t serialQueue=dispatch_queue_create("com.serial.queue", DISPATCH_QUEUE_SERIAL);

//創建一個并發隊列
dispatch_queue_t concurrentQueue=dispatch_queue_create("com.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);

//第一個參數為隊列名,第二個參數為隊列類型,當然,第二個參數人如果寫NULL,創建出來的也是一個串行隊列。然后我們在異步線程來執行這個隊列:

另外系統為我們準備了兩個隊列

  • main dispatch queue

功能跟主線程一樣,通過dispatch_get_main_queue()來獲取,提交到main queue的任務實際上都是在主線程執行的,所以這是一個串行隊列

dispatch_queue_t queue = dispatch_get_main_queue();
  • global dispatch queues

系統給每個應用提供四個全局的并發隊列,這四個隊列分別有不同的優先級:高、默認、低以及后臺,用戶不能去創建全局隊列,只能根據優先級去獲取:

dispatch_queue_t queue  = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

3.dispatch_sync&dispatch_async

執行隊列中任務的兩種方式,dispatch_sync是同步任務,dispatch_async是異步任務

1.用同步的方式執行任務(同步:synchronization), 只能在當前線程中執行任務,不具備開啟新線程的能力

/*
 *  第一個參數:該任務所在的隊列
 *  第二個參數:該任務要做的事情
 */
dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
  • 假如我指定的隊列A是串行隊列,則該隊列中只能有一個線程,也就是說我放在隊列A中的任務,所以必須得一個一個的執行。不僅如此,在上面我們還手動選擇了在隊列A中用同步的方式執行任務,這也限制了,隊列中的任務只能一個一個執行。

  • 假如我指定的隊列A是并行隊列,則該隊列中可以開辟多個線程去執行任務,雖然如此,但由于我們在上面手動選擇了在隊列A中用同步的方式執行線程,所以隊列A中的任務也只能一個一個去執行,不能開辟多線程同時執行

2.用異步的方式執行任務(異步:asynchronous),可以在新的線程中執行任務,具備開啟新線程的能力。

dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
  • 假如此時我指定的隊列B是并行隊列,則表明該隊列中可以存在多個線程,又因為我們采用的是異步的方式執行任務,所以在這個隊列的任務可以實現同時運行。

  • 假如此時我指定的隊列B是串行隊列,則表明該隊列中,只能有一個線程,所以盡管我采用異步的方式執行任務,但該隊列中的任務還是只能一個一個的運行。


4.創建的線程任務有四種執行方式


1. 串行隊列同步執行任務

  • 同步不具有開辟新線程的能力,不會開辟新的線程去執行任務,會在當前程序的主線程中執行任務。
  • 按照串行的方式去執行任務
-(void)syncSERIAL{
    NSLog(@"star");
    //不會開辟新的線程
    dispatch_queue_t queue=dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_SERIAL);
    dispatch_sync(queue, ^{
        NSLog(@"SERIAL_work_1 ");
    });
    dispatch_sync(queue, ^{
        NSLog(@"SERIAL_work_2 ");
    });
    dispatch_sync(queue, ^{
        NSLog(@"SERIAL_work_3 ");
    });
    
    NSLog(@"end");

}

執行結果

2016-07-20 20:08:09.695 GCD_Demo[8196:1029563] star
2016-07-20 20:08:09.696 GCD_Demo[8196:1029563] SERIAL_work_1 
2016-07-20 20:08:09.696 GCD_Demo[8196:1029563] SERIAL_work_2 
2016-07-20 20:08:09.696 GCD_Demo[8196:1029563] SERIAL_work_3 
2016-07-20 20:08:09.696 GCD_Demo[8196:1029563] end

由于是同步操作,不能開辟線程,所以都是在主線程并按照順序執行

2. 串行隊列異步執行任務

  • 異步具有創建新線程的能力,會開辟新的線程去執行任務
  • 按照串行的方式去執行任務
-(void)asyncSERIAL{
    NSLog(@"star");
    
    //會開辟新的線程,但是是串行執行任務
    dispatch_queue_t queue=dispatch_queue_create("ki", DISPATCH_QUEUE_SERIAL);
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:3];
        NSLog(@"SERIAL_work_1 ");
    });
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"SERIAL_work_2 ");
    });
    dispatch_async(queue, ^{
        NSLog(@"SERIAL_work_3 ");
    });
    
    NSLog(@"end");

}

執行結果

2016-07-20 20:09:58.494 GCD_Demo[8213:1031268] star
2016-07-20 20:09:58.495 GCD_Demo[8213:1031268] end
2016-07-20 20:10:01.496 GCD_Demo[8213:1031315] SERIAL_work_1 
2016-07-20 20:10:03.502 GCD_Demo[8213:1031315] SERIAL_work_2 
2016-07-20 20:10:03.502 GCD_Demo[8213:1031315] SERIAL_work_3 

因為是異步操作,所以有個編號為2的子線程被開辟,但有因為是串行隊列,所以只開辟了一個線程。最終造就了三個任務順序執行。

3. 并行隊列同步執行任務

  • 同步不具有創建新線程的能力,不會開辟新的線程去執行任務,會在當前程序的主線程去執行任務
  • 按照同步的方式去執行任務
-(void)syncCONCURRENT{
    NSLog(@"star");
    //不會開辟新的線程
    //串行執行命令
    dispatch_queue_t queue=dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_CONCURRENT);
    dispatch_sync(queue, ^{
        [NSThread sleepForTimeInterval:3];
        NSLog(@"CONCURRENT_work_1 ");
    });
    dispatch_sync(queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"CONCURRENT_work_2 ");
    });
    dispatch_sync(queue, ^{
        NSLog(@"CONCURRENT_work_3 ");
    });
    
    NSLog(@"end");
}

執行結果

2016-07-20 20:13:03.753 GCD_Demo[8232:1033759] star
2016-07-20 20:13:06.755 GCD_Demo[8232:1033759] CONCURRENT_work_1 
2016-07-20 20:13:08.756 GCD_Demo[8232:1033759] CONCURRENT_work_2 
2016-07-20 20:13:08.756 GCD_Demo[8232:1033759] CONCURRENT_work_3 
2016-07-20 20:13:08.757 GCD_Demo[8232:1033759] end

雖然并行隊列決定了該隊列中可以有多個線程,但由于是同步操作,不能開辟線程,所以還都是在主線程中按順序執行。

4. 并發隊列異步執行任務(常用)

  • 異步具有創建新線程的能力,會開辟新的線程去執行任務,不會在當前程序的主線程去執行任務
  • 按照并發的方式去執行任務
-(void)asyncCONCURRENT{
    NSLog(@"star");
    
    //一個隊列 為 每個任務開辟一個線程
    dispatch_queue_t queue=dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:3];
        NSLog(@"CONCURRENT_work_1 ");
    });
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"CONCURRENT_work_2 ");
    });
    dispatch_async(queue, ^{
        NSLog(@"CONCURRENT_work_3 ");
    });
    
    NSLog(@"end");
}

執行結果

2016-07-20 20:18:26.768 GCD_Demo[8256:1038143] star
2016-07-20 20:18:26.768 GCD_Demo[8256:1038143] end
2016-07-20 20:18:26.769 GCD_Demo[8256:1038192] CONCURRENT_work_3 
2016-07-20 20:18:28.771 GCD_Demo[8256:1038179] CONCURRENT_work_2 
2016-07-20 20:18:29.773 GCD_Demo[8256:1038188] CONCURRENT_work_1 

并行隊列可以里可以有多個線程,同步執行的方式又可以開辟多個線程,所以這里實現了多個線程并行執行。


5.Dispatch Group

當我們想在gcd queue中所有的任務執行完畢之后做些特定事情的時候,也就是隊列的同步問題,如果隊列是串行的話,那將該操作最后添加到隊列中即可,但如果隊列是并行隊列的話,這時候就可以利用dispatch_group來實現了,dispatch_group能很方便的解決同步的問題。dispatch_group_create可以創建一個group對象,然后可以添加block到該組里面,下面看下它的一些用法:

  • dispatch_group_notify
    是通過異步的方式通知,所以,不會阻塞線程
-(void)asyncGroupNotify
{
    NSLog(@"star");
    dispatch_group_t group=dispatch_group_create();
    dispatch_queue_t queue=dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_async(group, queue, ^{
        [NSThread sleepForTimeInterval:1];
        NSLog(@"group_work_1");
    });
    dispatch_group_async(group, queue, ^{
        [NSThread sleepForTimeInterval:6];
        NSLog(@"group_work_2");
    });
    dispatch_group_async(group, queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"group_work_3");
    });
    
    dispatch_group_notify(group, queue, ^{
        NSLog(@"dispatch_group_Notify 結束");
    });
}

運行結果

2016-07-21 13:51:40.600 GCD_Demo[9044:1162213] star
2016-07-21 13:51:41.605 GCD_Demo[9044:1162359] group_work_1
2016-07-21 13:51:42.608 GCD_Demo[9044:1162389] group_work_3
2016-07-21 13:51:46.603 GCD_Demo[9044:1162349] group_work_2
2016-07-21 13:51:46.605 GCD_Demo[9044:1162349] dispatch_group_Notify 結束
  • dispatch_group_wait
    會阻塞當前線程,知道任務都完成時才會繼續執行下面的代碼
-(void)asyncGroupWait
{
    NSLog(@"star");
    dispatch_group_t group=dispatch_group_create();
    dispatch_queue_t queue=dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_async(group, queue, ^{
        [NSThread sleepForTimeInterval:1];
        NSLog(@"group_work_1");
    });
    dispatch_group_async(group, queue, ^{
        [NSThread sleepForTimeInterval:6];
        NSLog(@"group_work_2");
    });
    dispatch_group_async(group, queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"group_work_3");
    });
    
    //在此設置了一個12秒的等待時間,如果group的執行結束沒有到12秒那么就返回0
    //如果執行group的執行時間超過了12秒,那么返回非0 數值,
    //在使用dispatch_group_wait函數的時候,會阻塞當前線程,阻塞的時間 在wait函數時間值和當前group執行時間值取最小的。
    long kk=dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, 12 * NSEC_PER_SEC));
    if(kk==0)
    {
         NSLog(@"dispatch_group_wait 結果1");
    }
    else
    {
         NSLog(@"dispatch_group_wait 結果2");
    }
    
}

執行結果

2016-07-21 13:56:47.471 GCD_Demo[9065:1165380] star
2016-07-21 13:56:48.472 GCD_Demo[9065:1165494] group_work_1
2016-07-21 13:56:49.476 GCD_Demo[9065:1165502] group_work_3
2016-07-21 13:56:53.475 GCD_Demo[9065:1165485] group_work_2
2016-07-21 13:56:53.475 GCD_Demo[9065:1165380] dispatch_group_wait 結果1
  • dispatch_group_enter&dispatch_group_leave
    假如我們不想使用dispatch_group_async異步的將任務丟到group中去執行,這時候就需要用到dispatch_group_enter跟dispatch_group_leave方法,這兩個方法要配對出現,以下這兩種方法是等價的:
-(void)asyncGroupEnter
{
    // 群組-統一監控一組任務
    dispatch_group_t group = dispatch_group_create();
    
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    
    // 1> 入組 -> 之后的 block 會被 group 監聽
    // dispatch_group_enter 一定和 dispatch_group_leave 要配對出現
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        NSLog(@"dispatch_async_work1");
        
        // block 的末尾,所有任務執行完畢后,添加一個出組
        dispatch_group_leave(group);
    });
    
    //  再次入組
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:6];
        
        NSLog(@"dispatch_async_work1");
        
        // block 的末尾,所有任務執行完畢后,添加一個出組
        dispatch_group_leave(group);
    });
    
    // 群組結束
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"OVER");
    });  
    NSLog(@"come here");
}

執行結果

2016-07-21 15:21:40.707 GCD_Demo[9256:1205427] come here
2016-07-21 15:21:40.707 GCD_Demo[9256:1205465] dispatch_async_work1
2016-07-21 15:21:46.709 GCD_Demo[9256:1205460] dispatch_async_work1
2016-07-21 15:21:46.710 GCD_Demo[9256:1205427] OVER

6. Dispatch Block

添加到gcd隊列中執行的任務是以block的形式添加的,block封裝了需要執行功能,block帶來的開發效率提升就不說了,gcd跟block可以說是一對好基友,能夠很好的配合使用。

-(void)dispatchBlock
{
    dispatch_queue_t queue = dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_SERIAL);
    dispatch_block_t block=dispatch_block_create(0, ^{
        NSLog(@"dispatchBlock_work");
    });
    
    dispatch_sync(queue, block);
}

** 1.dispatch_block_wait**
當需要等待前面的任務執行完畢時,我們可以使用dispatch_block_wait這個接口,設置等待時間DISPATCH_TIME_FOREVER會一直等待直到前面的任務完成.用法跟dispatch_group_wait類似

-(void)dispatchBlockWait
{
    dispatch_queue_t queue = dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_SERIAL);
    dispatch_block_t block = dispatch_block_create(0, ^{
        NSLog(@"before sleep");
        [NSThread sleepForTimeInterval:6];
        NSLog(@"after sleep");
    });
    dispatch_async(queue, block);
    //等待前面的任務執行完畢
    long kk=dispatch_block_wait(block, dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC));
    if(kk==0)
    {
        NSLog(@"coutinue");
    }
    else
    {
        NSLog(@"timeOut!!!");
    }
}

執行結果

2016-07-21 16:28:38.313 GCD_Demo[9533:1251011] before sleep
2016-07-21 16:28:41.314 GCD_Demo[9533:1250971] timeOut!!!
2016-07-21 16:28:44.318 GCD_Demo[9533:1251011] after sleep

** 2.dispatch_block_notify**
dispatch_block_notify當觀察的某個block執行結束之后立刻通知提交另一特定的block到指定的queue中執行,該函數有三個參數,第一參數是需要觀察的block,第二個參數是被通知block提交執行的queue,第三參數是當需要被通知執行的block

-(void)dispatchBlockNotify
{
    dispatch_queue_t queue = dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_SERIAL);
    dispatch_block_t previousBlock = dispatch_block_create(0, ^{
        NSLog(@"previousBlock begin");
        [NSThread sleepForTimeInterval:2];
        NSLog(@"previousBlock done");
    });
    dispatch_async(queue, previousBlock);
    dispatch_block_t notifyBlock = dispatch_block_create(0, ^{
        NSLog(@"notifyBlock");
    });
    //當previousBlock執行完畢后,提交notifyBlock到global queue中執行
    dispatch_block_notify(previousBlock, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), notifyBlock);
}

執行結果

2016-07-21 16:38:19.756 GCD_Demo[9664:1261328] previousBlock begin
2016-07-21 16:38:21.762 GCD_Demo[9664:1261328] previousBlock done
2016-07-21 16:38:21.762 GCD_Demo[9664:1261329] notifyBlock

3. dispatch_block_cancel

可以取消提交到隊列的block

-(void)dispatchBlockCancel
{
    dispatch_queue_t queue = dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_CONCURRENT);
    dispatch_block_t block1 = dispatch_block_create(0, ^{
        NSLog(@"block1 begin");
        [NSThread sleepForTimeInterval:1];
        NSLog(@"block1 done");
    });
    dispatch_block_t block2 = dispatch_block_create(0, ^{
        NSLog(@"block2 ");
    });
    dispatch_async(queue, block1);
    dispatch_async(queue, block2);
    dispatch_block_cancel(block2);
}

執行結果

2016-07-21 16:50:28.140 GCD_Demo[9723:1272259] block1 begin
2016-07-21 16:50:29.144 GCD_Demo[9723:1272259] block1 done

7.dispatch_after

來延遲執行的GCD方法,因為在主線程中我們不能用sleep來延遲方法的調用,所以用它是最合適的,我們做一個簡單的例子:

-(void)dispatchAfter
{
    NSLog(@"dispatchAfter_star");
    int64_t time=2*NSEC_PER_SEC;
    
    dispatch_queue_t mainQueue=dispatch_get_main_queue();
    
        for (int i=0; i<5; i++) {
        dispatch_time_t disTime=dispatch_time(DISPATCH_TIME_NOW, time*i);

        dispatch_after(disTime, mainQueue, ^{
            NSLog(@"dispatchAfter_work");
        });
    }
    
}

執行結果

2016-07-21 16:12:07.204 GCD_Demo[9439:1237251] dispatchAfter_star
2016-07-21 16:12:07.211 GCD_Demo[9439:1237251] dispatchAfter_work
2016-07-21 16:12:09.398 GCD_Demo[9439:1237251] dispatchAfter_work
2016-07-21 16:12:11.205 GCD_Demo[9439:1237251] dispatchAfter_work
2016-07-21 16:12:13.205 GCD_Demo[9439:1237251] dispatchAfter_work
2016-07-21 16:12:15.205 GCD_Demo[9439:1237251] dispatchAfter_work

8.dispatch_apply

dispatch_apply類似一個for循環,會在指定的dispatch queue中運行block任務n次,如果隊列是并發隊列,則會并發執行block任務,dispatch_apply是一個同步調用,block任務執行n次后才返回。

-(void)dispatchApply
{
    dispatch_queue_t queue = dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_CONCURRENT);
    

    dispatch_apply(6, queue, ^(size_t i) {
        NSLog(@"do a job %zu times",i);

    });
    NSLog(@"go on");
}

執行結果

2016-07-21 17:04:54.558 GCD_Demo[9831:1284549] do a job 0 times
2016-07-21 17:04:54.564 GCD_Demo[9831:1284583] do a job 1 times
2016-07-21 17:04:54.564 GCD_Demo[9831:1284589] do a job 2 times
2016-07-21 17:04:54.564 GCD_Demo[9831:1284593] do a job 3 times
2016-07-21 17:04:54.564 GCD_Demo[9831:1284549] do a job 4 times
2016-07-21 17:04:54.564 GCD_Demo[9831:1284583] do a job 5 times
2016-07-21 17:04:54.566 GCD_Demo[9831:1284549] go on

9.dispatch_once

整個程序運行中只會執行一次,使用dispatch_once可以簡化代碼并且徹底保證線程安全,開發者根本無須擔心加鎖或者同步。所有問題都由GCD在底層處理。由于每次調用時都必須使用完全相同的標記,所以標記要聲明成static。所以用在單例模式上是最好的

static SingletonTimer * instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    instance = [[SingletonTimer alloc] init];
});

return instance;

10. dispatch_barrier_async

dispatch_barrier_async用于等待前面的任務執行完畢后自己才執行,而它后面的任務需等待它完成之后才執行。一個典型的例子就是數據的讀寫,通常為了防止文件讀寫導致沖突,我們會創建一個串行的隊列,所有的文件操作都是通過這個隊列來執行,比如FMDB,這樣就可以避免讀寫沖突。不過其實這樣效率是有提升的空間的,當沒有更新數據時,讀操作其實是可以并行進行的,而寫操作需要串行的執行


-(void)diapatchBarrier
{
    dispatch_queue_t queue = dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:6];
        NSLog(@"dispatch_async_work1");
    });
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"dispatch_async_work2");
    });
    dispatch_barrier_async(queue, ^{
        NSLog(@"dispatch_async_work3");
        [NSThread sleepForTimeInterval:1];
        
    });
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:1];
        NSLog(@"dispatch_async_work4");
    });
}

執行結果

2016-07-21 15:54:24.402 GCD_Demo[9354:1225160] dispatch_async_work2
2016-07-21 15:54:28.403 GCD_Demo[9354:1225152] dispatch_async_work1
2016-07-21 15:54:28.403 GCD_Demo[9354:1225152] dispatch_async_work3
2016-07-21 15:54:30.412 GCD_Demo[9354:1225152] dispatch_async_work4

11.dispatch_set_target_queue

1.系統的Global Queue是可以指定優先級的,那我們可以用到dispatch_set_target_queue這個方法來指定自己創建隊列的優先級

-(void)DispatchSet
{
    dispatch_queue_t serialDiapatchQueue=dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_SERIAL);
    dispatch_queue_t dispatchgetglobalqueue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
    dispatch_set_target_queue(serialDiapatchQueue, dispatchgetglobalqueue);
    dispatch_async(serialDiapatchQueue, ^{
        NSLog(@"我優先級低,先讓讓");
    });
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"我優先級高,我先block");
    });
}

執行結果

2016-07-21 17:22:02.512 GCD_Demo[9902:1297023] 我優先級高,我先block
2016-07-21 17:22:02.512 GCD_Demo[9902:1297035] 我優先級低,先讓讓

2.dispatch_set_target_queue除了能用來設置隊列的優先級之外,還能夠創建隊列的層次體系,當我們想讓不同隊列中的任務同步的執行時,我們可以創建一個串行隊列,然后將這些隊列的target指向新創建的隊列即可

-(void)dispatchSet2
{
    dispatch_queue_t targetQueue = dispatch_queue_create("target_queue", DISPATCH_QUEUE_SERIAL);
    dispatch_queue_t queue1 = dispatch_queue_create("queue1", DISPATCH_QUEUE_SERIAL);
    dispatch_queue_t queue2 = dispatch_queue_create("queue2", DISPATCH_QUEUE_CONCURRENT);
    
    
    dispatch_set_target_queue(queue1, targetQueue);
    dispatch_set_target_queue(queue2, targetQueue);
    
    dispatch_async(queue1, ^{
        [NSThread sleepForTimeInterval:3.f];
        NSLog(@"do job1");
        
    });
    dispatch_async(queue2, ^{
        [NSThread sleepForTimeInterval:2.f];
        NSLog(@"do job2");
        
    });
    dispatch_async(queue2, ^{
        [NSThread sleepForTimeInterval:1.f];
        NSLog(@"do job3");
        
    });
}

執行結果

2016-07-21 17:28:54.327 GCD_Demo[10043:1303853] do job1
2016-07-21 17:28:56.331 GCD_Demo[10043:1303853] do job2
2016-07-21 17:28:57.335 GCD_Demo[10043:1303853] do job3
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容