一、進(jìn)程和線程
1.什么是進(jìn)程
進(jìn)程是指在系統(tǒng)中正在運(yùn)行的一個(gè)應(yīng)用程序
每個(gè)進(jìn)程之間是獨(dú)立的,每個(gè)進(jìn)程均運(yùn)行在其專用且受保護(hù)的內(nèi)存空間內(nèi)

比如同時(shí)打開QQ、Xcode,系統(tǒng)就會(huì)分別啟動(dòng)2個(gè)進(jìn)程
通過(guò)“活動(dòng)監(jiān)視器”可以查看Mac系統(tǒng)中所開啟的進(jìn)程
2.什么是線程
1個(gè)進(jìn)程要想執(zhí)行任務(wù),必須得有線程(每1個(gè)進(jìn)程至少要有1條線程)
線程是進(jìn)程的基本執(zhí)行單元,一個(gè)進(jìn)程(程序)的所有任務(wù)都在線程中執(zhí)行
比如使用酷狗播放音樂(lè)、使用迅雷下載電影,都需要在線程中執(zhí)行

3.線程的串行
1個(gè)線程中任務(wù)的執(zhí)行是串行的
如果要在1個(gè)線程中執(zhí)行多個(gè)任務(wù),那么只能一個(gè)一個(gè)地按順序執(zhí)行這些任務(wù)
也就是說(shuō),在同一時(shí)間內(nèi),1個(gè)線程只能執(zhí)行1個(gè)任務(wù)
比如在1個(gè)線程中下載3個(gè)文件(分別是文件A、文件B、文件C)
二、多線程
1.什么是多線程
1個(gè)進(jìn)程中可以開啟多條線程,每條線程可以并行(同時(shí))執(zhí)行不同的任務(wù)
進(jìn)程?->車間,線程->車間工人
多線程技術(shù)可以提高程序的執(zhí)行效率
比如同時(shí)開啟3條線程分別下載3個(gè)文件(分別是文件A、文件B、文件C)
2.多線程的原理
同一時(shí)間,CPU只能處理1條線程,只有1條線程在工作(執(zhí)行)
多線程并發(fā)(同時(shí))執(zhí)行,其實(shí)是CPU快速地在多條線程之間調(diào)度(切換)
如果CPU調(diào)度線程的時(shí)間足夠快,就造成了多線程并發(fā)執(zhí)行的假象
思考:如果線程非常非常多,會(huì)發(fā)生什么情況?
CPU會(huì)在N多線程之間調(diào)度,CPU會(huì)累死,消耗大量的CPU資源
每條線程被調(diào)度執(zhí)行的頻次會(huì)降低(線程的執(zhí)行效率降低)
3.多線程的優(yōu)缺點(diǎn)
多線程的優(yōu)點(diǎn)
能適當(dāng)提高程序的執(zhí)行效率
能適當(dāng)提高資源利用率(CPU、內(nèi)存利用率)
多線程的缺點(diǎn)
開啟線程需要占用一定的內(nèi)存空間(默認(rèn)情況下,主線程占用1M,子線程占用512KB),如果開啟大量的線程,會(huì)占用大量的內(nèi)存空間,降低程序的性能
線程越多,CPU在調(diào)度線程上的開銷就越大
程序設(shè)計(jì)更加復(fù)雜:比如線程之間的通信、多線程的數(shù)據(jù)共享
4.多線程在iOS開發(fā)中的應(yīng)用
主線程:一個(gè)iOS程序運(yùn)行后,默認(rèn)會(huì)開啟1條線程,稱為“主線程”或“UI線程”
主線程的主要作用
顯示\刷新UI界面
處理UI事件(比如點(diǎn)擊事件、滾動(dòng)事件、拖拽事件等)
主線程的使用注意:別將比較耗時(shí)的操作放到主線程中。
耗時(shí)操作會(huì)卡住主線程,嚴(yán)重影響UI的流暢度,給用戶一種“卡”的壞體驗(yàn)
三、IOS 多線程 有三種主要方法
(1)NSThread
(2)NSOperation
(3)GCD
1.NSThread
調(diào)用方法如下:
如函數(shù)需要輸入?yún)?shù),可從object傳進(jìn)去。
(1) [NSThread detachNewThreadSelector:@selector(threadInMainMethod:) toTarget:self withObject:nil];
(2) NSThread* myThread = [[NSThread alloc] initWithTarget:self selector:@selector(threadInMainMethod:) object:nil];
[myThread start];
(3) [obj performSelectorInBackground:@selector(threadMe) withObject:nil];
提個(gè)問(wèn)題:如果某個(gè)ViewController里運(yùn)行了一個(gè)Thread,Thread還沒(méi)結(jié)束的時(shí)候,這個(gè)ViewController被Release了,結(jié)果會(huì)如何?
經(jīng)過(guò)的的測(cè)試,Thread不結(jié)束,ViewController一直保留,不會(huì)執(zhí)行dealloc方法。
2.NSOperation
NSoperation也是多線程的一種,NSopertaion有2種形式
(1) 并發(fā)執(zhí)行
并發(fā)執(zhí)行你需要重載如下4個(gè)方法
//執(zhí)行任務(wù)主函數(shù),線程運(yùn)行的入口函數(shù)
- (void)start
//是否允許并發(fā),返回YES,允許并發(fā),返回NO不允許。默認(rèn)返回NO
-(BOOL)isConcurrent
- (BOOL)isExecuting
//是否已經(jīng)完成,這個(gè)必須要重載,不然放在放在NSOperationQueue里的NSOpertaion不能正常釋放。
- (BOOL)isFinished
比如TestNSOperation:NSoperaion 重載上述的4個(gè)方法,
聲明一個(gè)NSOperationQueue, NSOperationQueue *queue = [[[NSOperationQueue alloc ] init] autorelease];
[queue addOperation:testNSoperation];
它會(huì)自動(dòng)調(diào)用TestNSOperation里的 start函數(shù),如果需要多個(gè)NSOperation,你需要設(shè)置queue的一些屬性,如果多個(gè)NSOperation之間又依賴關(guān)系,也可以設(shè)置,具體可以參考API 文檔。
(2)非并發(fā)執(zhí)行
-(void)main
只需要重載這個(gè)main方法就可以了。
3.GCD
下面首先來(lái)看GCD的使用:
dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
async表明異步運(yùn)行,block代表的是你要做的事情,queue則是你把任務(wù)交給誰(shuí)來(lái)處理了.(除了async,還有sync,delay,本文以async為例).
之所以程序中會(huì)用到多線程是因?yàn)槌绦蛲鶗?huì)需要讀取數(shù)據(jù),然后更新UI.為了良好的用戶體驗(yàn),讀取數(shù)據(jù)的操作會(huì)傾向于在后臺(tái)運(yùn)行,這樣以避免阻塞主線程.GCD里就有三種queue來(lái)處理.
1. Main queue:
顧名思義,運(yùn)行在主線程,由dispatch_get_main_queue獲得.和ui相關(guān)的就要使用Main Queue.
2.Serial quque(private dispatch queue)
每次運(yùn)行一個(gè)任務(wù),可以添加多個(gè),執(zhí)行次序FIFO. 通常是指程序員生成的,比如:
NSDate*da=[NSDate date];
NSString*daStr=[da description];
constchar*queueName=[daStr UTF8String];
dispatch_queue_t myQueue=dispatch_queue_create(queueName, NULL);
3.Concurrent queue(global dispatch queue):
可以同時(shí)運(yùn)行多個(gè)任務(wù),每個(gè)任務(wù)的啟動(dòng)時(shí)間是按照加入queue的順序,結(jié)束的順序依賴各自的任務(wù).使用dispatch_get_global_queue獲得.
所以我們可以大致了解使用GCD的框架:
dispatch_async(getDataQueue,^{
//獲取數(shù)據(jù),獲得一組后,刷新UI.
dispatch_aysnc (mainQueue,^{
//UI的更新需在主線程中進(jìn)行
};
}
)