2019 iOS面試題大全---全方面剖析面試
-
進(jìn)程
-
線程
-
進(jìn)程和線程的關(guān)系
-
多進(jìn)程
-
多線程
-
任務(wù)
-
隊(duì)列
-
iOS中的多線程
一咆瘟、 進(jìn)程:
- 1.進(jìn)程是一個(gè)具有一定獨(dú)立功能的程序關(guān)于某次數(shù)據(jù)集合的一次運(yùn)行活動(dòng),它是操作系統(tǒng)分配資源的基本單元.
- 2.進(jìn)程是指在系統(tǒng)中正在運(yùn)行的一個(gè)應(yīng)用程序诽里,就是一段程序的執(zhí)行過(guò)程,我們可以理解為手機(jī)上的一個(gè)app.
- 3.每個(gè)進(jìn)程之間是獨(dú)立的袒餐,每個(gè)進(jìn)程均運(yùn)行在其專用且受保護(hù)的內(nèi)存空間內(nèi),擁有獨(dú)立運(yùn)行所需的全部資源
二谤狡、 線程
- 1.程序執(zhí)行流的最小單元灸眼,線程是進(jìn)程中的一個(gè)實(shí)體.
- 2.一個(gè)進(jìn)程要想執(zhí)行任務(wù),必須至少有一條線程.應(yīng)用程序啟動(dòng)的時(shí)候,系統(tǒng)會(huì)默認(rèn)開啟一條線程,也就是主線程
三墓懂、 進(jìn)程和線程的關(guān)系
- 1.線程是進(jìn)程的執(zhí)行單元焰宣,進(jìn)程的所有任務(wù)都在線程中執(zhí)行
- 2.線程是 CPU 分配資源和調(diào)度的最小單位
- 3.一個(gè)程序可以對(duì)應(yīng)多個(gè)進(jìn)程(多進(jìn)程),一個(gè)進(jìn)程中可有多個(gè)線程,但至少要有一條線程
- 4.同一個(gè)進(jìn)程內(nèi)的線程共享進(jìn)程資源
四、 多進(jìn)程
打開mac的活動(dòng)監(jiān)視器捕仔,可以看到很多個(gè)進(jìn)程同時(shí)運(yùn)行
- 進(jìn)程是程序在計(jì)算機(jī)上的一次執(zhí)行活動(dòng)匕积。當(dāng)你運(yùn)行一個(gè)程序,你就啟動(dòng)了一個(gè)進(jìn)程榜跌。顯然闪唆,程序是死的(靜態(tài)的),進(jìn)程是活的(動(dòng)態(tài)的)钓葫。
- 進(jìn)程可以分為系統(tǒng)進(jìn)程和用戶進(jìn)程悄蕾。凡是用于完成操作系統(tǒng)的各種功能的進(jìn)程就是系統(tǒng)進(jìn)程,它們就是處于運(yùn)行狀態(tài)下的操作系統(tǒng)本身;所有由用戶啟動(dòng)的進(jìn)程都是用戶進(jìn)程瓤逼。進(jìn)程是操作系統(tǒng)進(jìn)行資源分配的單位笼吟。
- 進(jìn)程又被細(xì)化為線程库物,也就是一個(gè)進(jìn)程下有多個(gè)能獨(dú)立運(yùn)行的更小的單位霸旗。在同一個(gè)時(shí)間里,同一個(gè)計(jì)算機(jī)系統(tǒng)中如果允許兩個(gè)或兩個(gè)以上的進(jìn)程處于運(yùn)行狀態(tài)戚揭,這便是多進(jìn)程诱告。
五、 多線程
1.同一時(shí)間民晒,CPU只能處理1條線程精居,只有1條線程在執(zhí)行锄禽。多線程并發(fā)執(zhí)行,其實(shí)是CPU快速地在多條線程之間調(diào)度(切換)靴姿。如果CPU調(diào)度線程的時(shí)間足夠快沃但,就造成了多線程并發(fā)執(zhí)行的假象
2.如果線程非常非常多,CPU會(huì)在N多線程之間調(diào)度佛吓,消耗大量的CPU資源宵晚,每條線程被調(diào)度執(zhí)行的頻次會(huì)降低(線程的執(zhí)行效率降低)
3.多線程的優(yōu)點(diǎn):
能適當(dāng)提高程序的執(zhí)行效率
能適當(dāng)提高資源利用率(CPU、內(nèi)存利用率)4.多線程的缺點(diǎn):
開啟線程需要占用一定的內(nèi)存空間(默認(rèn)情況下维雇,主線程占用1M淤刃,子線程占用512KB),如果開啟大量的線程吱型,會(huì)占用大量的內(nèi)存空間逸贾,降低程序的性能
線程越多,CPU在調(diào)度線程上的開銷就越大
程序設(shè)計(jì)更加復(fù)雜:比如線程之間的通信津滞、多線程的數(shù)據(jù)共享
六铝侵、任務(wù)
就是執(zhí)行操作的意思,也就是在線程中執(zhí)行的那段代碼据沈。在 GCD 中是放在 block 中的哟沫。執(zhí)行任務(wù)有兩種方式:同步執(zhí)行(sync)和異步執(zhí)行(async)
- 同步(Sync):同步添加任務(wù)到指定的隊(duì)列中,在添加的任務(wù)執(zhí)行結(jié)束之前锌介,會(huì)一直等待嗜诀,直到隊(duì)列里面的任務(wù)完成之后再繼續(xù)執(zhí)行,即會(huì)阻塞線程孔祸。只能在當(dāng)前線程中執(zhí)行任務(wù)(是當(dāng)前線程隆敢,不一定是主線程),不具備開啟新線程的能力崔慧。
- 異步(Async):線程會(huì)立即返回拂蝎,無(wú)需等待就會(huì)繼續(xù)執(zhí)行下面的任務(wù),不阻塞當(dāng)前線程惶室∥伦裕可以在新的線程中執(zhí)行任務(wù),具備開啟新線程的能力(并不一定開啟新線程)皇钞。如果不是添加到主隊(duì)列上悼泌,異步會(huì)在子線程中執(zhí)行任務(wù)
七、隊(duì)列
隊(duì)列(Dispatch Queue):這里的隊(duì)列指執(zhí)行任務(wù)的等待隊(duì)列夹界,即用來(lái)存放任務(wù)的隊(duì)列馆里。隊(duì)列是一種特殊的線性表,采用 FIFO(先進(jìn)先出)的原則,即新任務(wù)總是被插入到隊(duì)列的末尾鸠踪,而讀取任務(wù)的時(shí)候總是從隊(duì)列的頭部開始讀取丙者。每讀取一個(gè)任務(wù),則從隊(duì)列中釋放一個(gè)任務(wù)
在 GCD 中有兩種隊(duì)列:串行隊(duì)列和并發(fā)隊(duì)列营密。兩者都符合 FIFO(先進(jìn)先出)的原則械媒。兩者的主要區(qū)別是:執(zhí)行順序不同,以及開啟線程數(shù)不同评汰。
串行隊(duì)列(Serial Dispatch Queue):
同一時(shí)間內(nèi)滥沫,隊(duì)列中只能執(zhí)行一個(gè)任務(wù),只有當(dāng)前的任務(wù)執(zhí)行完成之后键俱,才能執(zhí)行下一個(gè)任務(wù)兰绣。(只開啟一個(gè)線程,一個(gè)任務(wù)執(zhí)行完畢后编振,再執(zhí)行下一個(gè)任務(wù))缀辩。主隊(duì)列是主線程上的一個(gè)串行隊(duì)列,是系統(tǒng)自動(dòng)為我們創(chuàng)建的-
并發(fā)隊(duì)列(Concurrent Dispatch Queue):
同時(shí)允許多個(gè)任務(wù)并發(fā)執(zhí)行。(可以開啟多個(gè)線程踪央,并且同時(shí)執(zhí)行任務(wù))臀玄。并發(fā)隊(duì)列的并發(fā)功能只有在異步(dispatch_async)函數(shù)下才有效
image.png
八、iOS中的多線程
主要有三種:NSThread畅蹂、NSoperationQueue健无、GCD
1. NSThread:輕量級(jí)別的多線程技術(shù)
是我們自己手動(dòng)開辟的子線程,如果使用的是初始化方式就需要我們自己?jiǎn)?dòng)液斜,如果使用的是構(gòu)造器方式它就會(huì)自動(dòng)啟動(dòng)累贤。只要是我們手動(dòng)開辟的線程,都需要我們自己管理該線程少漆,不只是啟動(dòng)臼膏,還有該線程使用完畢后的資源回收
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(testThread:) object:@"我是參數(shù)"];
// 當(dāng)使用初始化方法出來(lái)的主線程需要start啟動(dòng)
[thread start];
// 可以為開辟的子線程起名字
thread.name = @"NSThread線程";
// 調(diào)整Thread的權(quán)限 線程權(quán)限的范圍值為0 ~ 1 。越大權(quán)限越高示损,先執(zhí)行的概率就會(huì)越高渗磅,由于是概率,所以并不能很準(zhǔn)確的的實(shí)現(xiàn)我們想要的執(zhí)行順序检访,默認(rèn)值是0.5
thread.threadPriority = 1;
// 取消當(dāng)前已經(jīng)啟動(dòng)的線程
[thread cancel];
// 通過(guò)遍歷構(gòu)造器開辟子線程
[NSThread detachNewThreadSelector:@selector(testThread:) toTarget:self withObject:@"構(gòu)造器方式"];
- performSelector...只要是NSObject的子類或者對(duì)象都可以通過(guò)調(diào)用方法進(jìn)入子線程和主線程始鱼,其實(shí)這些方法所開辟的子線程也是NSThread的另一種體現(xiàn)方式。
在編譯階段并不會(huì)去檢查方法是否有效存在脆贵,如果不存在只會(huì)給出警告
//在當(dāng)前線程医清。延遲1s執(zhí)行。響應(yīng)了OC語(yǔ)言的動(dòng)態(tài)性:延遲到運(yùn)行時(shí)才綁定方法
[self performSelector:@selector(aaa) withObject:nil afterDelay:1];
// 回到主線程丹禀。waitUntilDone:是否將該回調(diào)方法執(zhí)行完在執(zhí)行后面的代碼状勤,如果為YES:就必須等回調(diào)方法執(zhí)行完成之后才能執(zhí)行后面的代碼,說(shuō)白了就是阻塞當(dāng)前的線程双泪;如果是NO:就是不等回調(diào)方法結(jié)束持搜,不會(huì)阻塞當(dāng)前線程
[self performSelectorOnMainThread:@selector(aaa) withObject:nil waitUntilDone:YES];
//開辟子線程
[self performSelectorInBackground:@selector(aaa) withObject:nil];
//在指定線程執(zhí)行
[self performSelector:@selector(aaa) onThread:[NSThread currentThread] withObject:nil waitUntilDone:YES]
需要注意的是:如果是帶afterDelay的延時(shí)函數(shù),會(huì)在內(nèi)部創(chuàng)建一個(gè) NSTimer焙矛,然后添加到當(dāng)前線程的Runloop中葫盼。也就是如果當(dāng)前線程沒(méi)有開啟runloop,該方法會(huì)失效村斟。在子線程中贫导,需要啟動(dòng)runloop(注意調(diào)用順序)
[self performSelector:@selector(aaa) withObject:nil afterDelay:1];
[[NSRunLoop currentRunLoop] run];
而performSelector:withObject:只是一個(gè)單純的消息發(fā)送,和時(shí)間沒(méi)有一點(diǎn)關(guān)系蟆盹。所以不需要添加到子線程的Runloop中也能執(zhí)行
2孩灯、GCD 對(duì)比 NSOprationQueue
我們要明確NSOperationQueue與GCD之間的關(guān)系
GCD是面向底層的C語(yǔ)言的API,NSOpertaionQueue用GCD構(gòu)建封裝的逾滥,是GCD的高級(jí)抽象峰档。
1、GCD執(zhí)行效率更高寨昙,而且由于隊(duì)列中執(zhí)行的是由block構(gòu)成的任務(wù)讥巡,這是一個(gè)輕量級(jí)的數(shù)據(jù)結(jié)構(gòu),寫起來(lái)更方便
2舔哪、GCD只支持FIFO的隊(duì)列欢顷,而NSOperationQueue可以通過(guò)設(shè)置最大并發(fā)數(shù),設(shè)置優(yōu)先級(jí)捉蚤,添加依賴關(guān)系等調(diào)整執(zhí)行順序
3抬驴、NSOperationQueue甚至可以跨隊(duì)列設(shè)置依賴關(guān)系,但是GCD只能通過(guò)設(shè)置串行隊(duì)列缆巧,或者在隊(duì)列內(nèi)添加barrier(dispatch_barrier_async)任務(wù)怎爵,才能控制執(zhí)行順序,較為復(fù)雜
4、NSOperationQueue因?yàn)槊嫦驅(qū)ο笾鸦龋灾С諯VO鳖链,可以監(jiān)測(cè)operation是否正在執(zhí)行(isExecuted)、是否結(jié)束(isFinished)墩莫、是否取消(isCanceld)
- 實(shí)際項(xiàng)目開發(fā)中芙委,很多時(shí)候只是會(huì)用到異步操作,不會(huì)有特別復(fù)雜的線程關(guān)系管理狂秦,所以蘋果推崇的且優(yōu)化完善灌侣、運(yùn)行快速的GCD是首選
- 如果考慮異步操作之間的事務(wù)性,順序行裂问,依賴關(guān)系侧啼,比如多線程并發(fā)下載牛柒,GCD需要自己寫更多的代碼來(lái)實(shí)現(xiàn),而NSOperationQueue已經(jīng)內(nèi)建了這些支持
- 不論是GCD還是NSOperationQueue痊乾,我們接觸的都是任務(wù)和隊(duì)列皮壁,都沒(méi)有直接接觸到線程,事實(shí)上線程管理也的確不需要我們操心哪审,系統(tǒng)對(duì)于線程的創(chuàng)建蛾魄,調(diào)度管理和釋放都做得很好。而NSThread需要我們自己去管理線程的生命周期湿滓,還要考慮線程同步滴须、加鎖問(wèn)題,造成一些性能上的開銷
- 更多關(guān)于GCD:2019 iOS面試題-----多線程相關(guān)之GCD叽奥、死鎖扔水、dispatch_barrier_async、dispatch_group_async朝氓、Dispatch Semaphore