歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> iOS多線程GCD的簡單使用

iOS多線程GCD的簡單使用

日期:2017/3/1 9:19:23   编辑:Linux編程

在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