在瞭解多線程以前,咱們須要先認識一下什麼是 進程 和 線程。
**進程:**是在系統中運行的一個程序,每一個進程之間是獨立的,每一個進程均運行在其專有且受保護的內存空間內。
**線程:**一個進程想要執行任務,必須得有線程(至少一個線程),線程是進程的基本執行單元,一個進程的全部任務都必須在線程中執行。
**線程的串行:**一個線程中任務的執行是串行的,若是要在一個線程中執行多個任務,只能一個一個的按順序執行。
那麼如何多個任務同時進行?這 便引出了咱們的多線程!ios
###1.基本概念
一個進程中能夠開啓多個線程,每一個線程能夠併發/並行執行不一樣的任務,多線程能夠提交程序的執行效率。以下圖(同時執行任務ABC):
編程
###2.多線程的原理 同一時間,CPU只能執行一個線程,只有一個線程正在執行,多線程併發執行,實際上是CPU快速的在多個線程之間切換。若是CPU的切換線程的時間足夠快,就會形成多線程併發執行的假象。多線程
###3.多線程的優缺點
**優勢: **(1)能適當的提升程序的執行效率
(2)能適當的提升資源的利用率(CPU,內存)
缺點:(1)開啓線程會佔用必定的內存空間(主線程1M,子線程0.5M),若是開啓過多的線程會佔用大量的內存空間,下降程序的性能。
(2)線程越多,CPU在調度線程上的開銷就越大。 ###4.IOS中的多線程編程技術 IOS中有四種多線程的編程技術:併發
以上三種編程技術由上至下,抽象度層次是從低到高的,抽象度越高使用越簡單,也是Apple最推薦使用的。框架
NSThread有二種建立方式異步
//實方法例 NSThread *thread = [[NSThread alloc]initWithTarget:self self selector:@selector(threadMethod ) object:nil]; [thread start]; //類方法 [NSThread detachNewThreadSelector: @selector (threadMethod ) toTarget:self withObject:nil];
參數解析:
selector :線程執行的方法,只能有一個參數,並且不能有返回值
target :selector消息發送的對象
argument:傳輸給target的惟一參數,也能夠是nilasync
NSOperation的使用有兩種方式:一種是使用定義好的兩個類:NSInvocationOperation和NSBlockOperation,另外一種是繼承NSOperation。函數
建立 NSInvocationOperation性能
//直接執行會在主線程中順序執行 NSInvocationOperation * operation_1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run_A) object:nil]; [operation_1 start]; // 啓動任務 // 建立一個隊列,默認就是並行隊列 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; // 設置當前最大的執行數,能夠控制是並行還串行,爲1時就是串行 queue.maxConcurrentOperationCount = 1; // 將任務添加到隊列中任務就自動執行了 [queue addOperation: operation_1];
建立NSBlockOperationspa
// 至少會有一個任務在主線程中執行,其餘任務會被放到其餘線程中執行 NSBlockOperation *blockOperation_1 = [NSBlockOperation blockOperationWithBlock:^{ [self run_A]; }]; [blockOperation_1 addExecutionBlock:^{ [self run_B]; }]; [opertion start];
###3.繼承 NSOperation
#import <Foundation/Foundation.h> @interface CustomOperation :NSOperation @end #import"CustomOperation.h" -(void)main{ NSLog(@"%@",[NSTread currentThread]); }
##4、GCD GCD是Apple開發的一個多核編程的解決方法。該方法在MAC OS X10.6首次推出,隨後引用到IOS4.0中。GCD是一個替代諸如:NSThread,NSOperationQueue,NSInvocationOperation等技術的很高效和強大的技術。
GCD隊列:分爲串行隊列(DISPATCH_QUEUE_SERIAL)和並⾏隊列(DISPATCH_QUEUE_CONCURRENT)。
** 系統提供的GCD隊列:**
**主隊列:**使用 dispatch_get_main_queue 函數來獲取和主線程關聯的串行隊列
**全局隊列:**系統提供的一個全局並行的隊列,使用 dispatch_get_global_queue 函數獲取
系統提供的dispatch方法:
//主線程執行一次 dispatch_async(dispatch_get_main_queue(), ^{ //task }); //後臺執行 dispatch_async (dispatch_get_global_queue(0,0), ^{ //task }) //執行一次 static dispatch_once _t onceToken; dispatch_once(& onceToken,^{ //task }); //延遲執行 int sec = 2; dispatch_after(dispatch_time (DISPATCH_TIME_NOW , (int64_t) (sec * NSEC_PER_SEC)), dispatch_get_main_queue(),^{ //task })
###1.同步
同步任務:dispatch_sync,會阻塞後面的任務,必需當前任務完成後才能執行下一個
dispatch_sync(dispatch_get_main_queue(), ^{ self.imagView_1.image = [self downloadImage_one]; });
###2.異步
異步執行:dispatch_async,不會阻塞後面的任務,任務會立刻返回下一個任務不須要等待,當這個任務完成後會通知主線程.
dispatch_async(dispatch_get_main_queue(), ^{ [self run_D]; }); dispatch_async(dispatch_get_main_queue(), ^{ [self run_B]; }); dispatch_async(dispatch_get_main_queue(), ^{ [self run_C]; });
dispatch_get_main_queue() 獲取主隊列,主隊列中的任務都會在主線程中執行, 是一個串行隊列
###3.串行
自定義的串行隊列,中異步執行任務,隊列會把任務放到一個新的線程中按順序執行
dispatch_queue_t serialQueue = dispatch_queue_create("串行隊列", DISPATCH_QUEUE_SERIAL); dispatch_async(serialQueue, ^{ [self run_A]; }); dispatch_async(serialQueue, ^{ [self run_B]; }); dispatch_async(serialQueue, ^{ [self run_C]; }); */
###4.並行
dispatch_get_global_queue() 全局隊列,是一個並行隊列,能夠將隊列中的任務放到不一樣的線程中執行
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ [self run_A]; }); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ [self run_B]; }); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [self run_C]; });
任務執行的優先級
DISPATCH_QUEUE_PRIORITY_HIGH 2 //最高 DISPATCH_QUEUE_PRIORITY_DEFAULT 0 //中等(默認) DISPATCH_QUEUE_PRIORITY_LOW (-2) //低 DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN //後臺執行
若是在並行隊列中同步執行任務,那麼這些任務都會在主線程中按順序執行,也就沒有併發性了。
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [self run_A]; }); dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [self run_B]; }); dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [self run_C]; });
自定義的並行隊列中異步執行任務,隊列會把任務放到不一樣的線程中執行
dispatch_queue_t concurrentlQueue = dispatch_queue_create("並行隊列", DISPATCH_QUEUE_CONCURRENT); dispatch_sync(concurrentlQueue, ^{ [self run_A]; }); dispatch_sync(concurrentlQueue, ^{ [self run_B]; }); dispatch_sync(concurrentlQueue, ^{ [self run_C]; });
##5、NSOperation與GCD的區別 **一、底層實現:**GCD的底層是用C來實現的,NSOperation底層從ios4開始也是用的GCD來實現的。 **二、取消任務:**在NSOperationQueue中,咱們能夠隨時取消已經設定要準備執行的任務(固然,已經開始的任務就沒法阻⽌了),而GCD無法中止已經加入queue的block(實際上是有的,但須要許多複雜的代碼)。 ** 三、依賴關係:**NSOperation可以方便地設置依賴關係,咱們可讓⼀個Operation依賴於另外一 個Operation,這樣的話儘管兩個Operation處於同一個並行隊列中,但前者會直到後者執行完畢後再執⾏。 **四、監放任務的執行狀況:**咱們能將KVO應用在NSOperation中,能夠監聽一個Operation是否完成或取消,這樣子能比GCD更加有效地掌控咱們執行的後臺任務。 **五、優先級:**在NSOperation中,咱們可以設置NSOperation的priority優先級,可以使同一個並行隊列中的任務區分前後地執行,⽽在GCD中,咱們只能區分不一樣任務隊列的優先級,若是要區分block任務的優先級,也須要大量的複雜代碼。 **六、代碼復⽤:**咱們可以對NSOperation進行繼承,在這之上添加成員變量與成員方法,提⾼整個代碼的復⽤度,這比簡單地將block任務排⼊入執⾏隊列更有⾃由度,可以在其之上添加更多⾃定製的功能。