iOS多線程GCD的簡單使用

在iOS開發中,蘋果提供了三種多線程技術,分別是:程序員

(1)NSThread多線程

(2)NSOperation異步

(3)GCDasync

簡單介紹一下GCD的使用。spa

GCD全稱 Grand Central Dispatch,能夠稱之爲大中央調度。實際上GCD是管理着一個線程池,如何建立線程,如何回收線程,以及分配多少個線程,這些都是GCD來控制的。在開發中,程序員是不用操做線程的相關事情,程序員只須要把應該作的操做放到相應的隊列裏面便可。線程

一:自定義隊列3d

GCD中有多種隊列,其中自定義的隊列有兩種:串行隊列和並行隊列code

1:串行隊列:隊列中的任務只會順序執行,且一次只可以執行一個任務。也就是說,執行完一個任務後,纔會執行下一個任務blog

2:並行隊列:能夠一次執行多個任務。好比說並行隊列中有10個任務,能夠一次執行3個任務,這三個任務哪一個先執行完了,再接着執行剩下的任務。隊列

注意:不管是串行隊列仍是並行隊列,他們都是FIFO(先進先出)的。也就是說,不管是哪一種隊列,任務進隊列的時間越早,其執行的時間就越早(只不過某些狀況下任務執行的結束時間是不肯定的)。

GCD中有兩種操做,分別是同步操做和異步操做

1:同步操做:不會新開線程

2:異步操做:會開啓新的線程

兩種操做和兩種隊列,組合爲4種狀況,實際上,在開發中,有些組合基本上是不會用到的。下面用程序描述一下四種組合。

組合一:串行隊列+同步操做(不會新建線程,並且任務是一個一個的執行,所以實際上就是順序執行),代碼以下:

- (void)gcdDemo1
{
    //串行隊列+同步操做
    dispatch_queue_t queue = dispatch_queue_create("gcddemo", DISPATCH_QUEUE_SERIAL);
    for(int i = 0; i < 10; ++i){
        dispatch_sync(queue, ^{
            NSLog(@"%@ %d",[NSThread currentThread],i);
        });
    }
}

執行結果:

number = 1,說明是主線程,沒有新開線程。

組合二:串行隊列+異步操做(由於任務要一個一個的執行,可是由於是異步操做,因此會開啓一個新的線程,全部的任務都在新的線程上執行),代碼以下:

- (void)gcdDemo1
{
    dispatch_queue_t queue = dispatch_queue_create("gcddemo", DISPATCH_QUEUE_SERIAL);
    //串行隊列+異步操做
    for (int i = 0; i < 10; ++i){
        dispatch_async(queue, ^{
            NSLog(@"%@ %d",[NSThread currentThread],i);
        });
    }
}

執行結果:

number = 2,說明開啓了一個新的子線程,但仍然是順序執行。

組合三:並行隊列+同步操做(由於同步操做不會開啓新的線程,所以,即便並行隊列能夠一次開始多個任務,但實際上仍舊是每一個任務都在主線程上執行,且按順序執行)。代碼以下:

- (void)gcdDemo2
{
    dispatch_queue_t queue = dispatch_queue_create("gcddemo", DISPATCH_QUEUE_CONCURRENT);
    //並行隊列+同步任務
    for(int i = 0; i < 10; ++i){
        dispatch_sync(queue, ^{
            NSLog(@"%@ %d",[NSThread currentThread],i);
        });
    }
}

執行結果:

沒有開啓新的線程,且按順序執行。

組合四:並行隊列+異步操做(並行隊列會一次開始多個任務,且異步操做能夠開啓新的線程,所以同一時刻可能會同時執行多個任務,開啓多個線程,且每一個任務的結束時間是不肯定的)。代碼以下:

- (void)gcdDemo2
{
    dispatch_queue_t queue = dispatch_queue_create("gcddemo", DISPATCH_QUEUE_CONCURRENT);
    //並行隊列+異步任務
    for(int i = 0; i < 10; ++i){
        dispatch_async(queue, ^{
            NSLog(@"%@ %d",[NSThread currentThread],i);
        });
    }
}

執行結果:

能夠看到,開啓了多個線程,且任務不是按順序執行完的。

二:全局隊列

爲了方便開發,蘋果還提供了有全局隊列,全局隊列其實是並行隊列,所以,全局隊列的執行結果和並行隊列的執行結果是一致的。代碼以下:

全局隊列+同步任務:

- (void)gcdDemo3
{
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    //全局隊列+同步任務
    for (int i = 0; i < 10; ++i){
        //同步任務
        dispatch_sync(queue, ^{
            NSLog(@"%@ %d",[NSThread currentThread],i);
        });
    }
}

執行結果:

全局隊列+異步任務:

- (void)gcdDemo3
{
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    //全局隊列+異步任務
    for(int i = 0; i < 10; ++i){
        dispatch_async(queue, ^{
            NSLog(@"%@ %d",[NSThread currentThread],i);
        });
    }
}

執行結果:

三:主隊列

蘋果還提供了一種隊列是主隊列,主隊列是串行隊列,可是和串行隊列又有差別。主隊列上的任務都應該在主線程上順序執行,沒有異步的概念。也就是說,即便是異步任務在主隊列上執行,也不會開啓新的線程。

主隊列+異步任務:

- (void)gcdDemo4
{
    dispatch_queue_t queue = dispatch_get_main_queue();
    //主隊列+異步任務
    for(int i = 0; i < 10; ++i){
        dispatch_async(queue,^{
            NSLog(@"%@ %d",[NSThread currentThread],i);
        });
    }
}

執行結果:

能夠看到,沒有開啓新的線程,且是順序執行。

主隊列+同步任務(會阻塞線程),代碼以下:

- (void)gcdDemo4
{
    dispatch_queue_t queue = dispatch_get_main_queue();
    //主隊列+同步任務,會阻塞
    for(int i = 0; i < 10; ++i){
        dispatch_sync(queue, ^{
            NSLog(@"%@ %d",[NSThread currentThread],i);
        });
    }
}

阻塞緣由:

主隊列中自己是有一個任務A的(主任務),且該任務A尚未執行完。在執行任務A的過程當中,又插入了新的同步任務B。咱們知道,串行隊列中,必須先執行完一個任務後,才能繼續執行另外一個任務。此時的狀況時:

若想繼續執行任務A,須要先把任務B執行完,若想繼續執行任務B,須要先把任務A執行完,所以形成了阻塞。

在開發中,應該避免這種阻塞的狀況。

相關文章
相關標籤/搜索