歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

iOS多線程GCD的簡單使用

 

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

 

(1)NSThread

 

(2)NSOperation

 

(3)GCD

 

簡單介紹一下GCD的使用。

 

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

 

一:自定義隊列

 

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

 

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

 

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執行完,因此造成了阻塞。

 

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

Copyright © Linux教程網 All Rights Reserved