多線程:防止主線程堵塞夯到,增加運(yùn)行效率。
The term thread is used to refer to a separate path of execution for code.
The term process is used to refer to a running executable, which can encompass multiple threads.
線程用于指代一個獨(dú)立執(zhí)行的代碼路徑
進(jìn)程用于指代一個可執(zhí)行程序,他可以包含多個線程
進(jìn)程:
正在進(jìn)行中的程序被稱為進(jìn)程,負(fù)責(zé)程序運(yùn)行的內(nèi)存分配;每一個進(jìn)程都有自己獨(dú)立的虛擬內(nèi)存空間
進(jìn)程是并發(fā)執(zhí)行的程序,在執(zhí)行過程中分配和管理資源的基本單位,是一個動態(tài)概念,竟?fàn)幱嬎銠C(jī)系統(tǒng)資源的基本單位倒彰。每一個進(jìn)程都有一個自己的地址空間审洞,即進(jìn)程空間
進(jìn)程又可有單線程進(jìn)程與多線程進(jìn)程兩種。
線程:
線程是進(jìn)程中一個獨(dú)立的執(zhí)行路徑(控制單元)待讳,是進(jìn)程的一部分芒澜,一個進(jìn)程中至少包含一條線程,即主線程创淡。
在網(wǎng)絡(luò)或多用戶環(huán)境下痴晦,一個服務(wù)器通常需要接收大量且不確定數(shù)量用戶的并發(fā)請求,為每一個請求都創(chuàng)建一個進(jìn)程顯然是行不通的琳彩,——無論是從系統(tǒng)資源開銷方面或是響應(yīng)用戶請求的效率方面來看誊酌。因此,操作系統(tǒng)中線程的概念便被引進(jìn)了露乏。一個沒有線程的進(jìn)程可以被看作是單線程的碧浊。
一個線程中任務(wù)的執(zhí)行是串行的, 也就是說同一時間內(nèi)一個線程只能執(zhí)行一個任務(wù)
線程:主線程、非主線程瘟仿。
主線程:
一個 iOS 程序運(yùn)行后, 默認(rèn)會開啟一條線程, 成為"主線程"或者"UI 線程"
主線程的主要作用:
顯示/刷新 UI 界面
處理 UI 事件(比如點(diǎn)擊事件, 滾動事件, 拖拽事件)
主線程的注意點(diǎn):
不要將比較耗時的操作放到主線程
耗時操作會卡住主線程, 嚴(yán)重影響 UI 的流暢度, 給用戶一種 "卡"的壞體檢
//獲得主線程:
[NSThread mainThread];
//獲得當(dāng)前線程:
[NSThread currentThread];
判斷是否為主線程:
// 類方法
BOOL isMainA = [NSThread isMainThread];
// 對象方法
BOOL isMainB = [thread isMainThread];
//返回值為1, 就是主線程
線程 進(jìn)程區(qū)別箱锐、聯(lián)系:
進(jìn)程擁有一個完整的虛擬地址空間,不依賴于線程而獨(dú)立存在劳较;
線程是進(jìn)程的一部分驹止,沒有自己的地址空間,與進(jìn)程內(nèi)的其他線程一起共享分配給該進(jìn)程的所有資源观蜗。
線程可以有效地提高系統(tǒng)的執(zhí)行效率臊恋,但并不是在所有計算機(jī)系統(tǒng)中都是適用的,如某些很少做進(jìn)程調(diào)度和切換的實時系統(tǒng)墓捻。使用線程的好處是有多個任務(wù)需要處理機(jī)處理時捞镰,減少處理機(jī)的切換時間;而且毙替,線程的創(chuàng)建和結(jié)束所需要的系統(tǒng)開銷也比進(jìn)程的創(chuàng)建和結(jié)束要小得多岸售。最適用使用線程的系統(tǒng)是多處理機(jī)系統(tǒng)和網(wǎng)絡(luò)系統(tǒng)或分布式系統(tǒng)。
一個線程可以創(chuàng)建和撤消另一個線程厂画,同一進(jìn)程中的多個線程之間可以并發(fā)執(zhí)行凸丸。
每個iOS應(yīng)用程序都有個專門用來更新顯示UI界面、處理用戶的觸摸事件的主線程袱院,因此不能將其他太耗時的操作放在主線程中執(zhí)行屎慢,不然會造成主線程堵塞(出現(xiàn)卡機(jī)現(xiàn)象)瞭稼,帶來極壞的用戶體驗。一般的解決方案就是將那些耗時的操作放到另外一個線程中去執(zhí)行腻惠。
多線程
一個進(jìn)程可以開啟多條線程,每條線程可以并行執(zhí)行不同的任務(wù)
多線程:多個線程并發(fā)執(zhí)行的技術(shù)
多線程原理
同一時間,CPU 只能處理一條線程, 只有一條線程在工作
多線程并發(fā)執(zhí)行,其實是 CPU 快速的在多條線程之間調(diào)度(切換)
如果 CPU 調(diào)度線程的時間足夠快, 就造成了多線程并發(fā)執(zhí)行的假象
老CPU不能做到多線程同時執(zhí)行环肘,而是在很短時間內(nèi)來回切換,給我們造成假象集灌;現(xiàn)在的多核CPU能同時執(zhí)行線程悔雹。
iOS中多線程技術(shù)有4種:
NSThread
NSOperation
GCD(Grand Central Dispatch)
Pthreads
區(qū)別、使用
抽象由低到高欣喧,抽象高就越簡單腌零。
- NSThread經(jīng)過蘋果封裝,完全面相對象唆阿,直接操控線程對象益涧,生命周期需要手動管理。
- NSOperation多用于網(wǎng)絡(luò)中驯鳖。
- GCD多用于本機(jī)處理上闲询,解析大數(shù)據(jù),能自動管理線程的生命周期(創(chuàng)建線程浅辙、調(diào)度任務(wù)嘹裂、銷毀線程),完全不需要我們管理摔握,且使用了block而更加方便寄狼、靈活。
多線程的好處:
(1)易于調(diào)度氨淌。
(2)提高并發(fā)性泊愧。
(3)開銷少。創(chuàng)建線程比創(chuàng)建進(jìn)程要快盛正。
(4)利于充分發(fā)揮多處理器的功能删咱。
進(jìn)程和線程的關(guān)系:
(1)一個線程只能屬于一個進(jìn)程,而一個進(jìn)程可以有多個線程豪筝,但至少有一個線程痰滋。
(2)資源分配給進(jìn)程,同一進(jìn)程的所有線程共享該進(jìn)程的所有資源续崖。
(3)處理機(jī)分給線程敲街,即真正在處理機(jī)上運(yùn)行的是線程。
(4)線程在執(zhí)行過程中严望,需要協(xié)作同步多艇。不同進(jìn)程的線程間要利用消息通信的辦法實現(xiàn)同步。線程是指進(jìn)程內(nèi)的一個執(zhí)行單元,也是進(jìn)程內(nèi)的可調(diào)度實體.
進(jìn)程與線程的區(qū)別:
(1)調(diào)度:線程作為調(diào)度和分配的基本單位像吻,進(jìn)程作為擁有資源的基本單位
(2)并發(fā)性:不僅進(jìn)程之間可以并發(fā)執(zhí)行峻黍,同一個進(jìn)程的多個線程之間也可并發(fā)執(zhí)行
(3)擁有資源:進(jìn)程是擁有資源的一個獨(dú)立單位复隆,線程不擁有系統(tǒng)資源,但可以訪問隸屬于進(jìn)程的資源
(4)系統(tǒng)開銷:在創(chuàng)建或撤消進(jìn)程時姆涩,由于系統(tǒng)都要為之分配和回收資源挽拂,導(dǎo)致系統(tǒng)的開銷明顯大于創(chuàng)建或撤消線程時的開銷。
進(jìn)程有獨(dú)立的地址空間骨饿,一個進(jìn)程崩潰后亏栈,在保護(hù)模式下不會對其它進(jìn)程產(chǎn)生影響,而線程只是一個進(jìn)程中的不同執(zhí)行路徑样刷。線程有自己的堆棧和局部變量,但線程之間沒有單獨(dú)的地址空間览爵,一個線程死掉就等于整個進(jìn)程死掉置鼻,所以多進(jìn)程的程序要比多線程的程序健壯,但在進(jìn)程切換時蜓竹,耗費(fèi)資源較大箕母,效率要差一些。但對于一些要求同時進(jìn)行并且又要共享某些變量的并發(fā)操作俱济,只能用線程嘶是,不能用進(jìn)程。
視頻播放器:下載視頻同時播放視頻蛛碌。
多線程就是同一時間有多條代碼語句同時執(zhí)行聂喇。
“線程”與“進(jìn)程”的聯(lián)系與區(qū)別?
一般運(yùn)行一個應(yīng)用程序,就生成了一個進(jìn)程, 這個進(jìn)程擁有自己的內(nèi)存空間,
這個進(jìn)程還可以內(nèi)部生成多個線程, 這些線程之間共用一個進(jìn)程的內(nèi)存空存空間,
所以線程之間共享內(nèi)存是很容易做到的,多線程協(xié)作比多進(jìn)程協(xié)作快一些,而且安全.
線程間通訊:
一個線程傳遞參數(shù)給另一個線程蔚携;一個線程執(zhí)行完任務(wù)后轉(zhuǎn)到另一個線程希太。方法如下:分線程回調(diào)
分線程回調(diào)主線程方法是什么,有什么作用酝蜒?
[self performSelectorOnMainThread:@selector(buttonGo2) withObject:nil waitUntilDone:YES];
[self performSelector:@selector(buttonGo2) onThread:[NSThread mainThread] withObject:nil waitUntilDone:YES];
需要即時刷新ui控件的時候誊辉,經(jīng)常使用。
線程池亡脑?
線程池是一堆項目的集合堕澄,就是一個線程隊列來管理這些線程對象,如果需要處理一些任務(wù)霉咨,可以從線程池中直接取線程蛙紫,而不是臨時創(chuàng)建線程。比如NSOperationQueue就是一個線程池途戒,管理NSOperation線程對象惊来。
(單核CPU快速在多條線程之間切換)
同步、異步的主要區(qū)別
在于會不會阻塞當(dāng)前線程棺滞,直到block中的任務(wù)執(zhí)行完畢裁蚁。
(是否開啟新線程矢渊,以及根據(jù)串行并行來決定開啟一條還是多條 )
同步任務(wù)優(yōu)先級高,在線程中有執(zhí)行順序枉证,不會開啟新的線程矮男。
異步任務(wù)優(yōu)先級低,在線程中執(zhí)行沒有順序室谚,看cpu閑不閑毡鉴。在主隊列中不會開啟新的線程,其他隊列會開啟新的線程秒赤。
同步:銀行轉(zhuǎn)賬猪瞬,數(shù)據(jù)庫操作
異步:加載圖片,然后主線程更新UI
隊列:
是管理線程的入篮,相當(dāng)于線程池,能管理線程什么時候執(zhí)行陈瘦。
不管是串行隊列(SerialQueue)還是并發(fā)隊列(ConcurrencyQueue),都是FIFO隊列潮售。也就意味著痊项,任務(wù)一定是一個一個地按照先進(jìn)先出的順序來執(zhí)行。
串行隊列:
任務(wù)會一個一個地執(zhí)行酥诽,只有前一個任務(wù)執(zhí)行完成鞍泉,才會繼續(xù)執(zhí)行下一個任務(wù)。隊列中的任務(wù)只會順序執(zhí)行(類似接力跑) 類似過收費(fèi)站肮帐。
并發(fā)隊列:
并發(fā)隊列會盡可能多地創(chuàng)建線程去執(zhí)行任務(wù)咖驮。并發(fā)隊列中的任務(wù)會按入隊的順序執(zhí)行任務(wù),但是哪個任務(wù)先完成是不確定的训枢。隊列中的任務(wù)通常會并發(fā)執(zhí)行(類似百米賽跑)
串行 并發(fā)的區(qū)別:
是否執(zhí)行完一個再執(zhí)行別的游沿。
主隊列:
每一個應(yīng)用開發(fā)程序?qū)?yīng)唯一一個主隊列,直接get即可肮砾;在多線程開發(fā)中诀黍,使用主隊列更新ui
全局隊列:
是系統(tǒng)開發(fā)的,直接拿過來(get)用就可以仗处;與并行隊列類似眯勾,但調(diào)試時,無法確認(rèn)操作所在隊列
串行隊列同步:操作不會新建線程婆誓、操作順序執(zhí)行
串行隊列異步:操作需要一個子線程吃环,會新建線程、線程的創(chuàng)建和回收不需要程序員參與洋幻,操作順序執(zhí)行郁轻,“最安全的選擇”
并發(fā)隊列同步:操作不會新建線程、操作順序執(zhí)行
并發(fā)隊列異步:操作會新建多個線程(有多少任務(wù),不見得就開n個線程執(zhí)行)好唯、操作無序執(zhí)行竭沫;隊列前如果有其他任務(wù),會等待前面的任務(wù)完成之后再執(zhí)行骑篙;場景:既不影響主線程蜕提,又不需要順序執(zhí)行的操作!
全局隊列同步:操作不會新建線程靶端、操作順序執(zhí)行
全局隊列異步:操作會新建多個線程谎势、操作無序執(zhí)行,隊列前如果有其他任務(wù)杨名,會等待前面的任務(wù)完成之后再執(zhí)行
主隊列異步:操作都應(yīng)該在主線程上順序執(zhí)行的脏榆,不存在異步的概念
主隊列同步:如果把主線程中的操作看成一個大的block,那么除非主線程被用戶殺掉台谍,否則永遠(yuǎn)不會結(jié)束须喂;主隊列中添加的同步操作永遠(yuǎn)不會被執(zhí)行,會死鎖典唇。
不同隊列嵌套dispathch_sync(同步)任務(wù)的結(jié)果
// 1.全局隊列镊折,都在主線程上執(zhí)行胯府,不會死鎖 dispatch_queue_priority_default
dispatch_queue_t q = dispatch_get_global_queue(dispatch_queue_priority_default, 0);
// 2.并行隊列介衔,都在主線程上執(zhí)行,不會死鎖 dispatch_queue_concurrent
dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo", dispatch_queue_concurrent);
// 3.串行隊列骂因,會死鎖炎咖,但是會執(zhí)行嵌套同步操作之前的代碼 dispatch_queue_serial
dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo", dispatch_queue_serial);
// 4.主隊列,直接死鎖 dispatch_get_main_queue();
dispatch_queue_t q = dispatch_get_main_queue();
dispatch_async(q, ^{
NSLog(@"同步任務(wù) %@", [NSThread currentThread]);
dispatch_sync(q, ^{
NSLog(@"同步任務(wù) %@", [NSThread currentThread]);
});
});
?任務(wù):執(zhí)行什么操作
?隊列:用來存放任務(wù)
主隊列的任務(wù)雖然會加到主線程中執(zhí)行寒波,但是如果主線程里也有任務(wù)就必須等主線程任務(wù)執(zhí)行完才輪到主隊列的乘盼。
主線程隊列中不能開啟同步,會阻塞主線程俄烁。只能開啟異步任務(wù)绸栅,開啟異步任務(wù)也不會開啟新的線程,只是降低異步任務(wù)的優(yōu)先級页屠,讓cpu空閑的時候才去調(diào)用粹胯。而同步任務(wù),會搶占主線程的資源辰企,會造成死鎖风纠。
串行/并行針對隊列 , 同步/異步針對任務(wù)
GCD 和 NSOperation、 NSThread簡介:
?NSThread:
–優(yōu)點(diǎn):NSThread 比其他兩個輕量級牢贸,使用簡單
–缺點(diǎn):需要自己管理線程的生命周期竹观、線程同步、加鎖、睡眠以及喚醒等臭增。線程同步對數(shù)據(jù)的加鎖會有一定的系統(tǒng)開銷
?NSOperation:–不需要關(guān)心線程管理懂酱,數(shù)據(jù)同步的事情,可以把精力放在自己需要執(zhí)行的操作上–NSOperation是面向?qū)ο蟮?br>
?GCD:–Grand Central Dispatch是由蘋果開發(fā)的一個多核編程的解決方案速址。
GCD 和 NSOperation比較:
- GCD的核心是C語言寫的系統(tǒng)服務(wù)玩焰,執(zhí)行和操作簡單高效,因此NSOperation底層也通過GCD實現(xiàn)芍锚,換個說法就是NSOperation是對GCD更高層次的抽象昔园,這是他們之間最本質(zhì)的區(qū)別.因此如果希望自定義任務(wù),建議使用NSOperation并炮;
2.依賴關(guān)系默刚,NSOperation可以設(shè)置兩個NSOperation之間的依賴,第二個任務(wù)依賴于第一個任務(wù)完成執(zhí)行逃魄,GCD無法設(shè)置依賴關(guān)系荤西,不過可以通過dispatch_barrier_async來實現(xiàn)這種效果;
3.KVO(鍵值對觀察)伍俘,NSOperation和容易判斷Operation當(dāng)前的狀態(tài)(是否執(zhí)行邪锌,是否取消),對此GCD無法通過KVO進(jìn)行判斷癌瘾;
4.優(yōu)先級觅丰,NSOperation可以設(shè)置自身的優(yōu)先級,但是優(yōu)先級高的不一定先執(zhí)行妨退,GCD只能設(shè)置隊列的優(yōu)先級妇萄,無法在執(zhí)行的block設(shè)置優(yōu)先級;
5.繼承咬荷,NSOperation是一個抽象類實際開發(fā)中常用的兩個類是NSInvocationOperation和NSBlockOperation冠句,同樣我們可以自定義NSOperation,GCD執(zhí)行任務(wù)可以自由組裝幸乒,沒有繼承那么高的代碼復(fù)用度懦底;
6.效率,直接使用GCD效率確實會更高效罕扎,NSOperation會多一點(diǎn)開銷聚唐,但是通過NSOperation可以獲得依賴,優(yōu)先級壳影,繼承拱层,鍵值對觀察這些優(yōu)勢,相對于多的那么一點(diǎn)開銷確實很劃算宴咧,魚和熊掌不可得兼根灯,取舍在于開發(fā)者自己;
7.取消任務(wù):在NSOperationQueue中,我們可以隨時取消已經(jīng)設(shè)定要準(zhǔn)備執(zhí)行的任務(wù)烙肺。
http://www.cnblogs.com/xiangrikui/p/5283746.html
GCD的核心概念是將一個任務(wù)添加到隊列纳猪,指定任務(wù)執(zhí)行的方法,然后執(zhí)行桃笙。 NSOperation則是直接將一個操作添加到隊列中氏堤。
參考:
http://www.reibang.com/p/9f2fc08f9947
http://www.tuicool.com/articles/YJJry2E
http://www.makaidong.com/博客園熱/32954.shtml
http://www.cnblogs.com/dsxniubility/p/4296937.html
http://blog.csdn.net/c386890506/article/details/51171898
http://www.reibang.com/p/266bec7c4dd2 //多線程面試題
http://www.reibang.com/p/3d430c25dd65 //多線程面試題
面試問題:
為什么多線程用GCD/NSOperation而不用NSOperation/GCD呢?
NSOpertaionQueue用GCD構(gòu)建封裝的,是GCD的高級抽象, GCD更接近底層
GCD僅僅支持FIFO隊列搏明,而NSOperationQueue中的隊列可以被重新設(shè)置優(yōu)先級鼠锈,調(diào)整順序
GCD不支持異步操作之間的依賴關(guān)系設(shè)置。
NSOperationQueue支持KVO星著,意味著我們可以觀察任務(wù)的執(zhí)行狀態(tài)购笆。項目中一般在哪用到多線程?
多線程一般用于耗時操作,如:
網(wǎng)絡(luò)請求
上傳,下載文件
讀取數(shù)據(jù)庫
文件操作
大循環(huán)GCD除了開線程,還可以用在什么地方虚循?
單例 (使用dispatch_once)
延遲執(zhí)行 (使用dispatch_after同欠,可以定義執(zhí)行任務(wù)的線程)
定時器 (使用dispatch_source_set_event_handler)
快速迭代/循環(huán)遍歷如何處理GCD造成的死鎖問題
將隊列改為非主隊列
將調(diào)度方式改為異步調(diào)度分別下載2張圖片后進(jìn)行組合:
可以使用GCD的柵欄函數(shù)或者隊列組,也可以使用NSOperation的依賴關(guān)系并行和并發(fā)的區(qū)別横缔?
并發(fā)是指兩個或多個事件在同一時間間隔內(nèi)發(fā)生铺遂。
例如單CPU的處理多線程。
并行是指兩個或者多個事件在同一時刻發(fā)生
例如多CPU的處理多線程茎刚。
串行(Sequential)襟锐、
并發(fā)(Concurrent)、
并行(parallel)
https://blog.csdn.net/qq_33290787/article/details/51790605
所寫多線程可能被分配到一個CPU內(nèi)核中執(zhí)行斗蒋,也可能被分配到不同CPU執(zhí)行捌斧,分配過程是操作系統(tǒng)所為笛质,不可人為控制泉沾。
排隊打咖啡的例子
一皇二后是并發(fā),二皇一后是并行妇押。
雙飛是并發(fā)跷究,4P是并行。
GCD和NSOperation有什么區(qū)別敲霍?
GCD是純C語言的API,NSOperation是基于GCD的OC版本封裝
GCD只支持FIFO的隊列俊马,NSOperation可以很方便地調(diào)整執(zhí)行順序,設(shè)置最大并發(fā)數(shù)量
NSOperationQueue可以輕松在operation間設(shè)置依賴關(guān)系肩杈,而GCD需要些很多代碼才能實現(xiàn)
NSOperationQueue支持KVO柴我,可以檢測operation是否正在執(zhí)行(isExecuted),是否結(jié)束(isFinisn),是否取消(isCancel)
GCD的執(zhí)行速度比NSOperation快
全局并發(fā)隊列和使用create函數(shù)創(chuàng)建的并發(fā)隊列主要區(qū)別
1.全局并發(fā)隊列在整個應(yīng)用程序中本身是默認(rèn)存在的扩然,并且有高級 默認(rèn) 低級 后臺四個優(yōu)先級并發(fā)隊列艘儒。而create函數(shù)創(chuàng)建的使我們自己實打?qū)崉?chuàng)建的
2.ios6.0前,GCD中使用create及retain的函數(shù) 最后都要一次release操作。而主隊列 全局并發(fā)隊列不需要我們手動release
3.柵欄函數(shù)只有在自己create的并發(fā)隊列中使用 而不能與全局并發(fā)隊列使用