多線程
首先介紹一下進(jìn)程和線程
進(jìn)程
- 進(jìn)程代表當(dāng)前運(yùn)行的一個(gè)程序(是系統(tǒng)分配資源的基本單位,可以理解為一個(gè)工廠)

Paste_Image.psng
線程
- 線程是cpu調(diào)度的最小單位,一個(gè)進(jìn)程含有一個(gè)線程或多個(gè)線程(應(yīng)用程序打開后會(huì)默認(rèn)開辟一個(gè)線程,叫做主線程或者UI線程,線程可以理解為工人里的一個(gè)工人
多線程的原理
- 同一時(shí)間,CPU只能處理1條線程,只有1條線程在工作(執(zhí)行)
- 多線程并發(fā)(同時(shí))執(zhí)行,其實(shí)是CPU快速地在多條線程之間調(diào)度(切換)
- 如果CPU調(diào)度線程的時(shí)間足夠快,就造成了多線程并發(fā)執(zhí)行的
- 創(chuàng)建的線程不易過多:
CPU會(huì)在N多線程之間調(diào)度,CPU會(huì)累死,消耗大量的CPU資源
每條線程被調(diào)度執(zhí)行的頻次會(huì)降低(線程的執(zhí)行效率降低)
多線程的缺點(diǎn)
- 創(chuàng)建線程是有開銷的,iOS下主要成本包括:內(nèi)核數(shù)據(jù)結(jié)構(gòu)(大約1KB)、??臻g(子線程512KB、主線程1MB,也可以使用-setStackSize:設(shè)置,但必須是4K的倍數(shù),而且最小是16K),創(chuàng)建線程大約需要90毫秒的創(chuàng)建時(shí)間
- 如果開啟大量的線程,會(huì)降低程序的性能
- 線程越多,CPU在調(diào)度線程上的開銷就越大
- 程序設(shè)計(jì)更加復(fù)雜:比如線程之間的通信、多線程的數(shù)據(jù)共享
主線程
-
什么是主線程
一個(gè)iOS程序運(yùn)行后,默認(rèn)會(huì)開啟1條線程,稱為“主線程”或“UI線程”
-
主線程的主要作用
顯示\刷新UI界面
處理UI事件(比如點(diǎn)擊事件、滾動(dòng)事件、拖拽事件等) -
主線程的使用注意
別將比較耗時(shí)的操作放到主線程中
耗時(shí)操作會(huì)卡住主線程,嚴(yán)重影響UI的流暢度,給用戶一種“卡”的壞體驗(yàn)
串行-并行-并發(fā)區(qū)別
- 串行:多個(gè)任務(wù)按順序執(zhí)行,類似于一個(gè)窗口辦公排隊(duì)
-
執(zhí)行順序 下載文件A->下載文件B->下載文件C,也可以認(rèn)為線程是進(jìn)程中的一條文件路徑
- 并行:多個(gè)任務(wù)同一時(shí)間一起執(zhí)行,類似于多個(gè)窗口辦公
-
并發(fā):多個(gè)任務(wù)看似是同一時(shí)間一起執(zhí)行,但實(shí)際上是CPU快速的輪轉(zhuǎn)切換造成的假象
- ps:我們使用多線程其實(shí)就是并發(fā)編程
使用多線程的優(yōu)點(diǎn):
- 可以減少多個(gè)任務(wù)執(zhí)行所需要的總時(shí)長,提升cpu利用率
使用多線程的缺點(diǎn):
- 1.線程需要耗費(fèi)系統(tǒng)資源 ,主線程要消耗??臻g的1MB資源,其他線程每個(gè)消耗512KB資源,不要過多使用
- 2.線程使用過多會(huì)使程序變得復(fù)雜,容易出現(xiàn)問題,不容易調(diào)試維護(hù)
耗時(shí)操作建議放到子線程中(后臺(tái)線程,非子線程)

多線程實(shí)現(xiàn)方案

打印當(dāng)前線程
NSLog(@"當(dāng)前線程 : %@",[NSThread currentThread]);
打印主線程
NSLog(@"主線程 : %@",[NSThread mainThread]);
判斷線程是否是主線程
BOOL isMainThread = [NSThread isMainThread];
休眠
[NSThread sleepForTimeInterval:3.0];
創(chuàng)建一個(gè)線程
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadAction) object:nil];
//設(shè)置線程名
thread.name = @"sq線程";
//設(shè)置線程優(yōu)先級(The thread’s priority, which is specified by a floating point number from 0.0 to 1.0, where 1.0 is highest priority.)
thread.threadPriority = 1.0f;
//需要手動(dòng)開啟線程
[thread start];
通過類方法創(chuàng)建一個(gè)線程(不推薦,設(shè)置不了相關(guān)屬性(如姓名等))
[NSThread detachNewThreadSelector:@selector(threadAction) toTarget:self withObject:nil];
在后臺(tái)執(zhí)行一個(gè)方法(耗時(shí)操作)
[self performSelectorInBackground:@selector(backgroundAction) withObject:nil];
在前臺(tái)執(zhí)行一個(gè)方法(如UI刷新操作需要在主線程中進(jìn)行)
[self performSelectorOnMainThread:@selector(mainAction) withObject:nil waitUntilDone:YES];
//參數(shù)1:需要在主線程中執(zhí)行的方法
//參數(shù)2:傳值
//參數(shù)3:是否阻塞線程(等待執(zhí)行完成后繼續(xù)執(zhí)行后面代碼)
A 線程鎖(比較耗資源,不建議用)
- 在線程鎖中只有一個(gè)線程執(zhí)行完之后其他線程才能進(jìn)入
//通常用self作標(biāo)簽
@synchronized (self) {}

