進程:正在進行中的程序被稱爲進程,負責程序運行的內存分配;每個進程都有本身獨立的虛擬內存空間ios
線程:線程是進程中一個獨立的執行路徑(控制單元);一個進程中至少包含一條線程,即主線程程序員
隊列 dispatch_queue_t,隊列名稱在調試時輔助,不管什麼隊列和任務,線程的建立和回收不須要程序員操做,有隊列負責。安全
串行隊列:隊列中的任務只會順序執行(相似跑步)多線程
dispatch_queue_t q = dispatch_queue_create(「....」, DISPATCH_QUEUE_SERIAL);併發
並行隊列:隊列中的任務一般會併發執行(相似賽跑)異步
dispatch_queue_t q = dispatch_queue_create("......", DISPATCH_QUEUE_CONCURRENT);async
全局隊列:是系統的,直接拿過來(GET)用就能夠;與並行隊列相似,但調試時,沒法確認操做所在隊列函數
dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);spa
主隊列:每個應用程序對應惟一一個主隊列,直接GET便可;在多線程開發中,使用主隊列更新UI線程
dispatch_queue_t q = dispatch_get_main_queue();
操做
dispatch_async 異步操做,會併發執行,沒法肯定任務的執行順序;
dispatch_sync 同步操做,會依次順序執行,可以決定任務的執行順序;
串行隊列同步:操做不會新建線程、操做順序執行
串行隊列異步:操做須要一個子線程,會新建線程、線程的建立和回收不須要程序員參與,操做順序執行,「最安全的選擇」
並行隊列同步:操做不會新建線程、操做順序執行
並行隊列異步:操做會新建多個線程(有多少任務,就開N個線程執行)、操做無序執行;隊列前若是有其餘任務,會等待前面的任務完成以後再執行;場景:既不影響主線程,又不須要順序執行的操做!
全局隊列異步:操做會新建多個線程、操做無序執行,隊列前若是有其餘任務,會等待前面的任務完成以後再執行
全局隊列同步:操做不會新建線程、操做順序執行
主隊列異步:操做都應該在主線程上順序執行的,不存在異步的概念
主隊列同步:若是把主線程中的操做當作一個大的Block,那麼除非主線程被用戶殺掉,不然永遠不會結束;主隊列中添加的同步操做永遠不會被執行,會死鎖
不一樣隊列嵌套dispathch_sync(同步)任務的結果
// 1.全局隊列,都在主線程上執行,不會死鎖 DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 2.並行隊列,都在主線程上執行,不會死鎖 DISPATCH_QUEUE_CONCURRENT
dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo", DISPATCH_QUEUE_CONCURRENT);
// 3.串行隊列,會死鎖,可是會執行嵌套同步操做以前的代碼 DISPATCH_QUEUE_SERIAL
dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo", DISPATCH_QUEUE_SERIAL);
// 4.主隊列,直接死鎖 dispatch_get_main_queue();
dispatch_queue_t q = dispatch_get_main_queue();
dispatch_sync(q, ^{
NSLog(@"同步任務 %@", [NSThread currentThread]);
dispatch_sync(q, ^{
NSLog(@"同步任務 %@", [NSThread currentThread]);
});
});
dispatch_sync同步應用場景
阻塞並行隊列的執行,要求某一操做執行後再進行後續操做,如用戶登陸
確保塊代碼以外的局部變量確實被修改
dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo", DISPATCH_QUEUE_CONCURRENT);
__block BOOL logon = NO;
dispatch_sync(q, ^{
NSLog(@"模擬耗時操做 %@", [NSThread currentThread]);
[NSThread sleepForTimeInterval:2.0f];
NSLog(@"模擬耗時完成 %@", [NSThread currentThread]);
logon = YES;
});
dispatch_async(q, ^{
NSLog(@"登陸完成的處理 %@", [NSThread currentThread]);
});
ios三種多線程技術:
1.NSThread
(1)使用NSThread對象創建一個線程很是方便
(2)可是!要使用NSThread管理多個線程很是困難,不推薦使用
(3)技巧!使用[NSThread currentThread]跟蹤任務所在線程,適用於這三種技術
2.NSOperation/NSOperationQueue
(1)是使用GCD實現的一套Objective-C的API
(2)是面向對象的線程技術
(3)提供了一些在GCD中不容易實現的特性,如:限制最大併發數量、操做之間的依賴關係
3.GCD —— Grand Central Dispatch
(1)是基於C語言的底層API
(2)用Block定義任務,使用起來很是靈活便捷
(3)提供了更多的控制能力以及操做隊列中所不能使用的底層函數
1---- 隊列和線程的區別:
隊列:是管理線程的,至關於線程池,能管理線程何時執行。
隊列分爲串行隊列和並行隊列等
串行隊列:隊列中的線程按順序執行(不會同時執行)
並行隊列:隊列中的線程會併發執行,可能會有一個疑問,隊列不是先進先出嗎,若是後面的任務執行完了,怎麼出去的了。這裏須要強調下,任務執行完畢了,不必定出隊列。只有前面的任務執行完了,纔會出隊列。
2----- 主線程隊列和GCD建立的隊列也是有區別的。
主線程隊列和GCD建立的隊列是不一樣的。在GCD中建立的隊列優先級沒有主隊列高,因此在GCD中的串行隊列開啓同步任務裏面沒有嵌套任務是不會阻塞主線程,只有一種可能致使死鎖,就是串行隊列裏,嵌套開啓任務,有可能會致使死鎖。
主線程隊列中不能開啓同步,會阻塞主線程。只能開啓異步任務,開啓異步任務也不會開啓新的線程,只是下降異步任務的優先級,讓cpu空閒的時候纔去調用。而同步任務,會搶佔主線程的資源,會形成死鎖。
3----- 線程:裏面有很是多的任務(同步,異步)
同步與異步的區別:
同步任務優先級高,在線程中有執行順序,不會開啓新的線程。
異步任務優先級低,在線程中執行沒有順序,看cpu閒不閒。在主隊列中不會開啓新的線程,其餘隊列會開啓新的線程。
4----主線程隊列注意:
下面代碼執行順序
1111
2222
主隊列異步 <NSThread: 0x8e12690>{name = (null), num = 1}
在主隊列開啓異步任務,不會開啓新的線程而是依然在主線程中執行代碼塊中的代碼。爲何不會阻塞線程?
> 主隊列開啓異步任務,雖然不會開啓新的線程,可是他會把異步任務下降優先級,等閒着的時候,就會在主線程上執行異步任務。
在主隊列開啓同步任務,爲何會阻塞線程?
> 在主隊列開啓同步任務,由於主隊列是串行隊列,裏面的線程是有順序的,先執行完一個線程才執行下一個線程,而主隊列始終就只有一個主線程,主線程是不會執行完畢的,由於他是無限循環的,除非關閉應用程序。所以在主線程開啓一個同步任務,同步任務會想搶佔執行的資源,而主線程任務一直在執行某些操做,不願放手。兩個的優先級都很高,最終致使死鎖,阻塞線程了。
/*
1.主隊列
*/
- (void)main_queue_deadlock
{
dispatch_queue_t q = dispatch_get_main_queue();
NSLog(@"1111");
dispatch_async(q, ^{
NSLog(@"主隊列異步任務 %@", [NSThread currentThread]);
});
NSLog(@"2222");
// 下面會形成線程死鎖
// dispatch_sync(q, ^{
// NSLog(@"主隊列同步 %@", [NSThread currentThread]);
// });
}
/**
* 2.並行隊列裏開啓同步任務是有執行順序的,只有異步纔沒有順序
*/
- (void)concurrent_queue
{
dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(q, ^{
NSLog(@"同步任務 %@1111111", [NSThread currentThread]);
dispatch_sync(q, ^{
NSLog(@"同步任務 %@2222222", [NSThread currentThread]);
});
dispatch_sync(q, ^{
NSLog(@"同步任務 %@333333", [NSThread currentThread]);
});
});
dispatch_sync(q, ^{
NSLog(@"同步任務 %@444444", [NSThread currentThread]);
});
dispatch_sync(q, ^{
NSLog(@"同步任務 %@555555", [NSThread currentThread]);
});
dispatch_sync(q, ^{
NSLog(@"同步任務 %@666666", [NSThread currentThread]);
});
}
/**
* 3.串行隊列開啓異步任務,是有順序的
*/
- (void)serial_queue
{
dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo", DISPATCH_QUEUE_SERIAL);
dispatch_async(q, ^{
NSLog(@"異步任務 %@1111111", [NSThread currentThread]);
});
dispatch_async(q, ^{
NSLog(@"異步任務 %@22222", [NSThread currentThread]);
});
dispatch_async(q, ^{
NSLog(@"異步任務 %@3333", [NSThread currentThread]);
});
dispatch_async(q, ^{
NSLog(@"異步任務 %@44444", [NSThread currentThread]);
});
}
/**
* 4.1.串行隊列開啓異步任務後嵌套同步任務形成死鎖
*/
- (void)serial_queue_deadlock2
{
dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo", DISPATCH_QUEUE_SERIAL);
dispatch_async(q, ^{
NSLog(@"異步任務 %@", [NSThread currentThread]);
// 下面開啓同步形成死鎖:由於串行隊列中線程是有執行順序的,須要等上面開啓的異步任務執行完畢,纔會執行下面開啓的同步任務。而上面的異步任務還沒執行完,要到下面的大括號纔算執行完畢,而下面的同步任務已經在搶佔資源了,就會發生死鎖。
dispatch_sync(q, ^{
NSLog(@"同步任務 %@", [NSThread currentThread]);
});
});
}
/**
* 4.2.串行隊列開啓同步任務後嵌套同步任務形成死鎖
*/
- (void)serial_queue_deadlock1
{
dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo", DISPATCH_QUEUE_SERIAL);
dispatch_sync(q, ^{
NSLog(@"同步任務 %@", [NSThread currentThread]);
// 下面開啓同步形成死鎖:由於串行隊列中線程是有執行順序的,須要等上面開啓的同步任務執行完畢,纔會執行下面開啓的同步任務。而上面的同步任務還沒執行完,要到下面的大括號纔算執行完畢,而下面的同步任務已經在搶佔資源了,就會發生死鎖。
dispatch_sync(q, ^{
NSLog(@"同步任務 %@", [NSThread currentThread]);
});
});
NSLog(@"同步任務 %@", [NSThread currentThread]);
}
/**
* 4.3.串行隊列開啓同步任務後嵌套異步任務不形成死鎖
*/
- (void)serial_queue1
{
dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo", DISPATCH_QUEUE_SERIAL);
dispatch_sync(q, ^{
NSLog(@"同步任務 %@", [NSThread currentThread]);
// 開啓異步,就會開啓一個新的線程,不會阻塞線程
dispatch_async(q, ^{
NSLog(@"異步任務 %@", [NSThread currentThread]);
});
});
NSLog(@"同步任務 %@", [NSThread currentThread]);
}