談到多線程就到說到線程和進程,就要說到NSThread、GCD、NSOperation!
基本知識
1. 進程(process)
進程是指在系統(tǒng)中正在運行的一個應用程序,就是一段程序的執(zhí)行過程。
每個進程之間是相互獨立的, 每個進程均運行在其專用且受保護的內(nèi)存空間內(nèi)。
進程是一個具有一定獨立功能的程序關(guān)于某次數(shù)據(jù)集合的一次運行活動,它是操作系統(tǒng)分配資源的基本單元。
進程狀態(tài):進程有三個狀態(tài),就緒,運行和阻塞。就緒狀態(tài)其實就是獲取了除cpu外的所有資源,只要處理器分配資源馬上就可以運行。運行態(tài)就是獲取了處理器分配的資源,程序開始執(zhí)行,阻塞態(tài),當程序條件不夠時,需要等待條件滿足時候才能執(zhí)行,如等待I/O操作的時候,此刻的狀態(tài)就叫阻塞態(tài)。
2. 線程(thread)
一個進程要想執(zhí)行任務,必須要有線程,至少有一條線程
一個進程的所有任務都是在線程中執(zhí)行
每個應用程序想要跑起來,最少也要有一條線程存在,其實應用程序啟動的時候我們的系統(tǒng)就會默認幫我們的應用程序開啟一條線程,這條線程也叫做'主線程',或者'UI線程'
3. 進程和線程的關(guān)系
線程是進程的執(zhí)行單元,進程的所有任務都在線程中執(zhí)行!
線程是 CPU 調(diào)用的最小單位
進程是 CPU 分配資源和調(diào)度的單位
一個程序可以對應多個進程,一個進程中可有多個線程,但至少要有一條線程
同一個進程內(nèi)的線程共享進程資源
舉個例子:進程就好比公司中的一個個部門,線程則代表著部門中的同事,而主線程當然是我們的老板了,一個公司不能沒有老板,一個程序不能沒有線程其實都是一個道理.
相同點:進程和線程都是有操作系統(tǒng)所提供的程序運行的基本單元,系統(tǒng)利用該基本單元實現(xiàn)系統(tǒng)對應用程序的并發(fā)性。
不同點:
進程和線程的主要差別在于他們是不同的操作系統(tǒng)資源管理方式。
進程有獨立的地址空間,一個進程crash后,在保護模式下不會對其他進程產(chǎn)生影響。
而線程只是一個進程中的不同執(zhí)行路徑。線程有自己的堆棧和局部變量,但線程之間沒有單獨的地址空間。一個線程crash就等于整個進程crash
多進程的程序比多線程的程序健壯,但在進程切換時,耗費資源較大,效率要差一些。但對于一些要求同時進行并且又要共享某些變量的并發(fā)操作,只能用線程,不能用進程。
優(yōu)缺點:
進程執(zhí)行開銷大,但利于資源的管理和保護。
線程執(zhí)行開銷小,但不利于資源的管理和保護。線程適合于在SMP(多核處理機)機器上運行。
4. 多線程
Mac、iPhone的操作系統(tǒng)OS X、iOS根據(jù)用戶的指示啟動應用程序后,首先便將包含在應用程序中的CPU命令列配置到內(nèi)存中。CPU從應用程序知道的地址開始,一個一個執(zhí)行CPU命令列。
在OC的if或for語句等控制語句或函數(shù)調(diào)用的情況下,執(zhí)行命令列的地址會遠離當前的位置(位置遷移)。但是,由于一個CPU一次只能執(zhí)行一個命令,不能執(zhí)行某處分開的并列的兩個命令,因此通過CPU執(zhí)行的CPU命令列就好比一條無分叉的大道,其執(zhí)行不會出現(xiàn)分歧。
這里所說的“1個CPU執(zhí)行的CPU命令列為一條無分叉路徑”,即為“線程”
這種無分叉路徑不只1條,存在有多條時即為“多線程”。1個CPU核執(zhí)行多條不同路徑上的不同命令。
OS X和iOS的核心XNU內(nèi)核在發(fā)生操作系統(tǒng)事件時(如每隔一定時間,喚起系統(tǒng)調(diào)用等情況)會切換執(zhí)行路徑。例如CPU的寄存器等信息保存到各自路徑專用的內(nèi)存塊中,從切換目標路徑專用的內(nèi)存塊中,復原CPU寄存器等信息,繼續(xù)執(zhí)行切換路徑的CPU命令列。這被稱為“上下文切換”
由于使用多線程的程序可以在某個線程和其他線程之間反復多次進行上下文切換,因此看上去就好像1個CPU核能夠并列地執(zhí)行多個線程一樣。而且在具有多個CPU核的情況下,就不是“看上去像”了,而是真的提供了多個CPU核并行執(zhí)行多個線程的技術(shù)。
這種利用多線程編程的技術(shù)就被稱為“多線程編程”
但是,多線程編程實際上是一種易發(fā)生各種問題的編程技術(shù)。比如多個線程更新相同資源會導致數(shù)據(jù)的不一致(數(shù)據(jù)競爭)、停止等待事件的線程會導致多個線程相互等待(死鎖)、使用太多線程會消耗大量內(nèi)存等。

主線程
一個程序運行后,默認會開啟 1 個線程,稱為“主線程”或“UI線程”
主線程一般用來
1. ?刷新 UI 界面
2. ?處理 UI 事件(比如:點擊、滾動、拖拽等事件)
主線程使用注意
1. ?別將耗時的操作放到主線程中
2. ?耗時操作會卡住主線程,嚴重影響UI的流暢度,給用戶一種卡的壞體驗
耗時操作演練
- (void)demo {
NSInteger count =1000*10;NSTimeInterval start =CACurrentMediaTime();
/*
1. 循環(huán)的速度很快
2. 棧區(qū)操作很快
3. 常量操作很快
4. 堆區(qū)操作速度不快
5. 循環(huán)消耗 CPU 資源
6. I / O 操作速度慢
*/
for(NSInteger i =0; i < count; i++) {
NSInteger num = i;
NSString*text =@"hello";
NSString*name = [NSString stringWithFormat:@"%@ - %zd", text, num];
NSLog(@"%@", name);? ?
}
NSLog(@"over %f",CACurrentMediaTime() - start);
}
多線程解決耗時操作示例代碼
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event {
// 直接調(diào)用//?
? [self demo];
//第一種方法
//? ? [self performSelectorInBackground:@selector(demo) withObject:nil];
//第二種方法
[NSThreaddetachNewThreadSelector:@selector(demo) toTarget:selfwithObject:nil];
// 第三種方法
//? ? dispatch_async(dispatch_get_global_queue(0, 0), ^{
//? ? ? ? [self demo];
//? ? });
}
多線程的原理

1. ?(單核CPU)同一時間,CPU 只能處理 1 個線程
換言之,同一時間只有 1 個線程在執(zhí)行
2. ?多線程同時執(zhí)行:
是 CPU 快速的在多個線程之間的切換
CPU 調(diào)度線程的時間足夠快,就造成了多線程的“同時”執(zhí)行的效果
3. ?如果線程數(shù)非常多
CPU 會在 N 個線程之間切換,消耗大量的 CPU 資源
每個線程被調(diào)度的次數(shù)會降低,線程的執(zhí)行效率降低
多線程優(yōu)/缺點
優(yōu)點
1. ?能適當提高程序的執(zhí)行效率
2. ?能適當提高資源的利用率(CPU,內(nèi)存)
3. ?線程上的任務執(zhí)行完成后,線程會自動銷毀
缺點
1. ?開啟線程需要占用一定的內(nèi)存空間(默認情況下,每一個線程都占 512 KB)
2. ?如果開啟大量的線程,會占用大量的內(nèi)存空間,降低程序的性能
3. ?線程越多,CPU 在調(diào)用線程上的開銷就越大
4. ?程序設(shè)計更加復雜,比如線程間的通信、多線程的數(shù)據(jù)共享

多線程技術(shù)方案
