在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執行完,所以形成了阻塞。
在開發中,應該避免這種阻塞的狀況。