1. 程式人生 > >GCD的8種搭配方式

GCD的8種搭配方式

OC中多執行緒方案中,一個比較常用的方案就是GCD
在GCD中有兩個概念:

佇列

任務

佇列 :

-1.序列佇列 :在一個時刻,只會排程一個任務線上程上執行(在一個時間點上,這個佇列中的任務,只有一個會被執行緒執行)
dispatch_queue_t queue = dispatch_queue_create("xiao", DISPATCH_QUEUE_SERIAL);
-2.並行佇列 :在同一時間,會有多個任務被排程,線上程上執行,每個任務被分配到不同的執行緒(在一個時間點上,這個佇列中的任務,可能會有多個,在不同的執行緒上同時執行)
dispatch_queue_t
queue = dispatch_queue_create("xiao", DISPATCH_QUEUE_CONCURRENT);
-3.全域性佇列 :是一個特殊的並行佇列,這個佇列右系統建立,拿來直接用就好
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
-4.主佇列 :是一種特殊的序列佇列,也是由系統建立
dispatch_queue_t queue = dispatch_get_main_queue();
並行佇列,序列佇列都遵守FIFO原則(先進先出)

任務:

-1.同步任務 :在當前執行緒中執行,放到這個執行緒的最後執行(這一時刻),若果後面還有任務,就加到它後面執行
dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
//第一個引數是佇列模式(傳入上面4中模式中的一種)
//第二個引數是要執行的任務
-2.非同步任務 :在新的執行緒中執行,指派一個空閒的執行緒來執行(這個任務之前沒有任務在執行,會被馬上執行)
dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

在GCD下,將一個任務放到摸一個執行緒執行,需要為它指派一個佇列,任務方式,因此會有8中組合方法.

-1.序列佇列 + 同步任務 :拿出一個任務,在當前執行緒執行,當執行完後,在從佇列中取出一個任務,在當前任務中執行;
- (void)gcdDemo2{

    // 建立一個序列佇列
    dispatch_queue_t queue = dispatch_queue_create("xiao", DISPATCH_QUEUE_SERIAL);

    // 把10個同步任務新增到序列佇列中
    for (int i = 0; i < 10; i++) {
        dispatch_sync(queue, ^{
            NSLog(@"%d-%@",i,[NSThread currentThread]);
        });
    }

}


##執行結果
2017-02-21 21:37:23.147 08-GCD序列佇列[5195:632507] 0-<NSThread: 0x60000007df40>{number = 1, name = main}
2017-02-21 21:37:23.148 08-GCD序列佇列[5195:632507] 1-<NSThread: 0x60000007df40>{number = 1, name = main}
2017-02-21 21:37:23.148 08-GCD序列佇列[5195:632507] 2-<NSThread: 0x60000007df40>{number = 1, name = main}
2017-02-21 21:37:23.148 08-GCD序列佇列[5195:632507] 3-<NSThread: 0x60000007df40>{number = 1, name = main}
2017-02-21 21:37:23.148 08-GCD序列佇列[5195:632507] 4-<NSThread: 0x60000007df40>{number = 1, name = main}
2017-02-21 21:37:23.149 08-GCD序列佇列[5195:632507] 5-<NSThread: 0x60000007df40>{number = 1, name = main}
2017-02-21 21:37:23.149 08-GCD序列佇列[5195:632507] 6-<NSThread: 0x60000007df40>{number = 1, name = main}
2017-02-21 21:37:23.149 08-GCD序列佇列[5195:632507] 7-<NSThread: 0x60000007df40>{number = 1, name = main}
2017-02-21 21:37:23.149 08-GCD序列佇列[5195:632507] 8-<NSThread: 0x60000007df40>{number = 1, name = main}
2017-02-21 21:37:23.149 08-GCD序列佇列[5195:632507] 9-<NSThread: 0x60000007df40>{number = 1, name = main}
-2.序列佇列 + 非同步任務 :拿出一個任務,在當前執行緒之外拿出一個執行緒來執行任務,當任務執行完畢之後,在從佇列中拿出一個任務在這個執行緒上執行
- (void)gcdDemo2{

    // 建立一個序列佇列
    dispatch_queue_t queue = dispatch_queue_create("xiao", DISPATCH_QUEUE_SERIAL);

    // 把10個非同步任務新增到序列佇列中
    for (int i = 0; i < 10; i++) {
        dispatch_async(queue, ^{
            NSLog(@"%d-%@",i,[NSThread currentThread]);
        });
    }

}

##執行結果
2017-02-21 21:35:36.440 08-GCD序列佇列[5165:630854] 0-<NSThread: 0x60800007dc40>{number = 3, name = (null)}
2017-02-21 21:35:36.440 08-GCD序列佇列[5165:630854] 1-<NSThread: 0x60800007dc40>{number = 3, name = (null)}
2017-02-21 21:35:36.440 08-GCD序列佇列[5165:630854] 2-<NSThread: 0x60800007dc40>{number = 3, name = (null)}
2017-02-21 21:35:36.441 08-GCD序列佇列[5165:630854] 3-<NSThread: 0x60800007dc40>{number = 3, name = (null)}
2017-02-21 21:35:36.441 08-GCD序列佇列[5165:630854] 4-<NSThread: 0x60800007dc40>{number = 3, name = (null)}
2017-02-21 21:35:36.441 08-GCD序列佇列[5165:630854] 5-<NSThread: 0x60800007dc40>{number = 3, name = (null)}
2017-02-21 21:35:36.441 08-GCD序列佇列[5165:630854] 6-<NSThread: 0x60800007dc40>{number = 3, name = (null)}
2017-02-21 21:35:36.441 08-GCD序列佇列[5165:630854] 7-<NSThread: 0x60800007dc40>{number = 3, name = (null)}
2017-02-21 21:35:36.442 08-GCD序列佇列[5165:630854] 8-<NSThread: 0x60800007dc40>{number = 3, name = (null)}
2017-02-21 21:35:36.442 08-GCD序列佇列[5165:630854] 9-<NSThread: 0x60800007dc40>{number = 3, name = (null)}
-3.並行佇列 + 同步任務 :有序的取出一個任務,放到當前執行緒執行,執行完畢之後在取出下一個任務執行
- (void)gcdDemo1{
    // 建立一個並行佇列
    dispatch_queue_t queue = dispatch_queue_create("xiao", DISPATCH_QUEUE_CONCURRENT);
    // 將10個同步任務新增到並行佇列中
    for (int i = 0; i < 10; i++) {
        dispatch_sync(queue, ^{
            NSLog(@"%d-%@",i,[NSThread currentThread]);
        });
    }
}

##執行結果
2017-02-21 22:20:19.479 09-GCD並行佇列[5297:647011] 0-<NSThread: 0x608000072200>{number = 1, name = main}
2017-02-21 22:20:19.480 09-GCD並行佇列[5297:647011] 1-<NSThread: 0x608000072200>{number = 1, name = main}
2017-02-21 22:20:19.482 09-GCD並行佇列[5297:647011] 2-<NSThread: 0x608000072200>{number = 1, name = main}
2017-02-21 22:20:19.482 09-GCD並行佇列[5297:647011] 3-<NSThread: 0x608000072200>{number = 1, name = main}
2017-02-21 22:20:19.483 09-GCD並行佇列[5297:647011] 4-<NSThread: 0x608000072200>{number = 1, name = main}
2017-02-21 22:20:19.483 09-GCD並行佇列[5297:647011] 5-<NSThread: 0x608000072200>{number = 1, name = main}
2017-02-21 22:20:19.483 09-GCD並行佇列[5297:647011] 6-<NSThread: 0x608000072200>{number = 1, name = main}
2017-02-21 22:20:19.483 09-GCD並行佇列[5297:647011] 7-<NSThread: 0x608000072200>{number = 1, name = main}
2017-02-21 22:20:19.483 09-GCD並行佇列[5297:647011] 8-<NSThread: 0x608000072200>{number = 1, name = main}
2017-02-21 22:20:19.484 09-GCD並行佇列[5297:647011] 9-<NSThread: 0x608000072200>{number = 1, name = main}
-4.並行佇列 + 非同步任務 :有序的取出多個任務,分配到不同的執行緒上同時執行,每當有一個執行緒執行完畢之後,會繼續從佇列中拿一個出來繼續執行,雖然取出的時候是有序的,但是每一個執行緒執行完畢的時間是不同的,不一定先執行的任務先完成,所以會有下面的結果
- (void)gcdDemo2{
    // 建立一個並行的佇列
    dispatch_queue_t queue = dispatch_queue_create("xiao", DISPATCH_QUEUE_CONCURRENT);
    // 將10個非同步任務新增到並行佇列中
    for (int i = 0; i < 10; i++) {
        dispatch_async(queue, ^{
            NSLog(@"%d-%@",i,[NSThread currentThread]);
        });
    }
}

##執行結果
2017-02-21 22:25:12.606 09-GCD並行佇列[5321:649930] 1-<NSThread: 0x60800007b3c0>{number = 4, name = (null)}
2017-02-21 22:25:12.606 09-GCD並行佇列[5321:649931] 0-<NSThread: 0x60800007b380>{number = 3, name = (null)}
2017-02-21 22:25:12.607 09-GCD並行佇列[5321:649933] 3-<NSThread: 0x60800007b500>{number = 6, name = (null)}
2017-02-21 22:25:12.607 09-GCD並行佇列[5321:649945] 2-<NSThread: 0x60800007b480>{number = 5, name = (null)}
2017-02-21 22:25:12.607 09-GCD並行佇列[5321:650010] 4-<NSThread: 0x60800007b540>{number = 7, name = (null)}
2017-02-21 22:25:12.607 09-GCD並行佇列[5321:649930] 5-<NSThread: 0x60800007b3c0>{number = 4, name = (null)}
2017-02-21 22:25:12.608 09-GCD並行佇列[5321:649931] 7-<NSThread: 0x60800007b380>{number = 3, name = (null)}
2017-02-21 22:25:12.608 09-GCD並行佇列[5321:650011] 6-<NSThread: 0x600000260e80>{number = 8, name = (null)}
2017-02-21 22:25:12.609 09-GCD並行佇列[5321:650012] 8-<NSThread: 0x600000260840>{number = 9, name = (null)}
2017-02-21 22:25:12.609 09-GCD並行佇列[5321:649933] 9-<NSThread: 0x60800007b500>{number = 6, name = (null)}
-5.全域性佇列 + 同步任務 :同-3.

-6.全域性佇列 + 非同步任務 :同-4.

-7.主佇列 + 非同步任務 : 同-2.

-8.主佇列 + 同步任務 : 這裡需要注意一個問題,主佇列是每次那一個任務出來給主執行緒執行(此時主執行緒必須處於空閒狀態,如果不空閒,就不能完成任務),但是如果當前執行緒就是主執行緒,那麼當執行到交給主執行緒執行任務時,主執行緒也在等待任務完成,所以一直處在非空閒狀態,而任務由於主執行緒沒有處於空閒狀態而不被執行,這個時候就產生了矛盾,導致程式崩潰;如果當前執行緒不是主執行緒,就同-1.不會產生任何問題