GCD隊列使用

使用GCD前,先對隊列總結一下:

串行和并發(fā)

GCD中隊列分為兩種:串行隊列、并發(fā)隊列。
串行隊列:任務按在隊列里的先后順序執(zhí)行,先進先出(FIFO),一個任務執(zhí)行完成后,才會執(zhí)行下一個任務(實際實現(xiàn)是在一個線程中完成所有任務,這個線程可能是主線程,也可能是子線程)。
并發(fā)隊列:任務無序同時執(zhí)行(實際實現(xiàn)是在多個子線程中執(zhí)行)。

同步和異步

任務的執(zhí)行方式分為同步和異步兩種,同步和異步是以是否在當前線程執(zhí)行區(qū)分的。
同步執(zhí)行:任務都在當前線程中執(zhí)行,并且會阻塞當前線程。
異步執(zhí)行:任務會開辟新的線程,并在新的線程中執(zhí)行,不會阻塞當前線程。

組合四種隊列

兩種隊列和兩種執(zhí)行方式組合起來就形成了四種隊列:串行同步隊列、串行異步隊列、并發(fā)同步隊列、并發(fā)異步隊列。四種隊列區(qū)別如下(先貼結論,后面驗證):

串行同步隊列:任務都在當前線程執(zhí)行(同步),并且順序執(zhí)行(串行)
串行異步隊列:任務都在開辟的新的子線程中執(zhí)行(異步),并且順序執(zhí)行(串行)
并發(fā)同步隊列:任務都在當前線程執(zhí)行(同步),但是是順序執(zhí)行的(并發(fā)的特性并沒有體現(xiàn)出來)
并發(fā)異步隊列:任務在開辟的多個子線程中執(zhí)行(異步),并且是同時執(zhí)行的(并發(fā))

注:由上面的特性即可看出,我們平時對GCD使用最多的是并發(fā)異步隊列。

準備工作

研究隊列類型之間的區(qū)別前,先看一下GCD中生成隊列的方法:
方法一:dispatch_queue_create:可以生成串行和并發(fā)隊列

// 前兩個方法生成的是串行隊列;第三個生成的是并發(fā)隊列
dispatch_queue_create("com.serial.queue", DISPATCH_QUEUE_SERIAL);
dispatch_queue_create("com.serial.queue", NULL);
dispatch_queue_create("com.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);

方法二:dispatch_get_global_queue:只能生成并發(fā)隊列

// 只能生成并發(fā)隊列
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

驗證四種隊列

打印方法:

#pragma mark - private methods
- (void)p_printThread:(int)index {
    NSLog(@"%@-------%d", [NSThread currentThread], index);
}

1.串行同步隊列

dispatch_queue_t queue = dispatch_queue_create("com.serial.queue", NULL);
    dispatch_sync(queue, ^(){
        [self p_printThread:1];
    });
    dispatch_sync(queue, ^(){
        [self p_printThread:2];
    });
    dispatch_sync(queue, ^(){
        [self p_printThread:3];
    });
    dispatch_sync(queue, ^(){
        [self p_printThread:4];
    });

打印結果:

<NSThread: 0x608000068380>{number = 1, name = main}-------1
<NSThread: 0x608000068380>{number = 1, name = main}-------2
<NSThread: 0x608000068380>{number = 1, name = main}-------3
<NSThread: 0x608000068380>{number = 1, name = main}-------4

結論:在串行同步隊列中,任務都在當前線程執(zhí)行(同步),并且順序執(zhí)行(串行)。
注:打印的結果都是主線程,是因為當前線程是主線程,這并不是說同步就是在主線程執(zhí)行的。

2.串行異步隊列

dispatch_queue_t queue = dispatch_queue_create("com.serial.queue", DISPATCH_QUEUE_SERIAL);
    dispatch_async(queue, ^(){
        [self p_printThread:1];
    });
    dispatch_async(queue, ^(){
        [self p_printThread:2];
    });
    dispatch_async(queue, ^(){
        [self p_printThread:3];
    });
    dispatch_async(queue, ^(){
        [self p_printThread:4];
    });

打印結果:

 <NSThread: 0x60800007b440>{number = 3, name = (null)}-------1
 <NSThread: 0x60800007b440>{number = 3, name = (null)}-------2
 <NSThread: 0x60800007b440>{number = 3, name = (null)}-------3
 <NSThread: 0x60800007b440>{number = 3, name = (null)}-------4

結論:在串行異步隊列中,任務都在新開辟的子線程中執(zhí)行(異步),并且順序執(zhí)行(串行)。

3.并發(fā)同步隊列

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_sync(queue, ^(){
        [self p_printThread:1];
    });
    dispatch_sync(queue, ^(){
        [self p_printThread:2];
    });
    dispatch_sync(queue, ^(){
        [self p_printThread:3];
    });
    dispatch_sync(queue, ^(){
        [self p_printThread:4];
    });

打印結果:

 <NSThread: 0x6080000790c0>{number = 1, name = main}-------1
 <NSThread: 0x6080000790c0>{number = 1, name = main}-------2
 <NSThread: 0x6080000790c0>{number = 1, name = main}-------3
 <NSThread: 0x6080000790c0>{number = 1, name = main}-------4

結論:在并發(fā)同步隊列中,任務都在當前線程中執(zhí)行(同步),但是是順序執(zhí)行的(并發(fā)的特性并沒有體現(xiàn)出來,因為同步會阻塞當前線程)。

4.并發(fā)異步隊列

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(queue, ^(){
        [self p_printThread:1];
    });
    dispatch_async(queue, ^(){
        [self p_printThread:2];
    });
    dispatch_async(queue, ^(){
        [self p_printThread:3];
    });
    dispatch_async(queue, ^(){
        [self p_printThread:4];
    });

打印結果:

 <NSThread: 0x618000066700>{number = 4, name = (null)}-------2
 <NSThread: 0x60000006cc80>{number = 6, name = (null)}-------4
 <NSThread: 0x60000006ccc0>{number = 3, name = (null)}-------1
 <NSThread: 0x6080000635c0>{number = 5, name = (null)}-------3

結論:在并發(fā)異步隊列中,任務在多個新開辟的子線程中執(zhí)行(異步),并且是同時無序地執(zhí)行的(并發(fā))

分析總結

由上面代碼示例可以看出,串行隊列就是在一個線程執(zhí)行的隊列:如果是當前線程,那就是串行同步隊列(因為同步機制會阻塞當前線程),如果是新開辟的子線程,就是串行異步隊列;并發(fā)隊列如果是在當前線程中執(zhí)行,就是并發(fā)同步隊列,在新開辟的多個子線程中執(zhí)行就是并發(fā)異步隊列。
綜上所述,我們平時使用最多的自然是并發(fā)異步隊列,比如開辟多個子線程下載圖片、文件等。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容