iOS中哪些技術(shù)可以實(shí)現(xiàn)開辟線程岖圈,他們之間的聯(lián)系和區(qū)別是什么食呻?
創(chuàng)建方式:
NSThread近范、NSOperation催束、GCD
聯(lián)系:
三種編程方式都是針對線程操作來講的集峦,從上到下,抽象層次是從低到高抠刺,抽象程度越到的使用越簡單塔淤;
區(qū)別:
(1)NSThread:
優(yōu)點(diǎn):NSThread比其他兩個輕量級,使用簡單
缺點(diǎn):需要自己管理線程的生命周期速妖、線程同步高蜂、加鎖、睡眠以及喚醒等罕容。線程同步對數(shù)據(jù)的加鎖會有一定的系統(tǒng)開銷
(2)NSOpearation:
— 不需要關(guān)心線程管理备恤,數(shù)據(jù)同步的事情稿饰,可以把精力放在自己需要執(zhí)行的操作上
— NSOpearation是面向?qū)ο蟮模o予OC語言實(shí)現(xiàn)的API露泊。兩種默認(rèn)實(shí)現(xiàn):NSInvocationOperation和NSBlockOperation喉镰。
(3)GCD:
— Grand Central Dispatch是有蘋果開發(fā)的一個多核編程的解決方案。iOS4.0+才能使用惭笑,是替代NStread,NSOperation的高效和強(qiáng)大的技術(shù)侣姆;
— GCD是基于C語言的API,提供了非常多強(qiáng)大的函數(shù)沉噩,GCD會自動管理線程的聲明周期(創(chuàng)建線程捺宗、調(diào)度任務(wù)、銷毀線程)屁擅。程序員只需要告訴GCD想要執(zhí)行什么任務(wù)偿凭,不需要編寫任何線程管理代碼。我們在編寫GCD相關(guān)代碼的時候派歌,面對的函數(shù)弯囊,而不是方法。GCD中的函數(shù)大多數(shù)都以dispatch開頭胶果。
線程 和 進(jìn)程
(1)進(jìn)程:運(yùn)行中的應(yīng)用程序匾嘱,操作系統(tǒng)稱之為一個進(jìn)程;編寫->編譯(.m->.o)->鏈接(把扇貝一部生成的.o文件連城引用程序)早抠;當(dāng)用戶啟動應(yīng)用程序霎烙,首先操作系統(tǒng)給啟動的應(yīng)用程序分配地址空間,然后把程序加載到代碼段蕊连,操作系統(tǒng)再幫你生成一個主線程悬垃,用于執(zhí)行代碼(給它分配CPU)
(2)線程:是一個執(zhí)行序列,是CPU分配的單位甘苍,如何分配靠操作系統(tǒng)的調(diào)度算法尝蠕,線程必須存在于一個進(jìn)程中,但是一個進(jìn)程可以包含多個執(zhí)行序列载庭,也就是多個線程看彼;
線程和進(jìn)程的聯(lián)系和區(qū)別
定義:
? ? ? 進(jìn)程是系統(tǒng)進(jìn)行資源分配和調(diào)度的一個獨(dú)立單位;線程是進(jìn)程的實(shí)體囚聚,是cpu調(diào)度和分派的基本單位靖榕;
關(guān)系:
? ? 一個線程可以創(chuàng)建和撤銷另一個線程;同一個進(jìn)程中的多個線程之間可以并發(fā)執(zhí)行顽铸。
區(qū)別:
? ? (1)簡而言之茁计,一個程序至少有一個進(jìn)程,一個進(jìn)程至少有一個線程? ?
??? (2)線程的劃分尺度小于進(jìn)程谓松,使得多線程程序的并發(fā)性高
??? (3)進(jìn)程在執(zhí)行過程中擁有獨(dú)立的內(nèi)存單元簸淀,而多個線程共享內(nèi)存瓶蝴,從而極大的提高了程序的運(yùn)行效率
??? (4)線程不能獨(dú)立執(zhí)行,必須依存于應(yīng)用程序中租幕,由應(yīng)用程序提供多個線程執(zhí)行控制
??? (5)多線程的意義在于一個應(yīng)用程序中,有多個執(zhí)行部分可以同時執(zhí)行拧簸。但操作系統(tǒng)不會將多線程看做多個應(yīng)用劲绪,來實(shí)現(xiàn)進(jìn)程的調(diào)度和管理及資源分配。
一盆赤、NSThread:
????? 創(chuàng)建一個線程贾富,每一個線程都有一個入口函數(shù),稱之為線程函數(shù)牺六,線程從線程函數(shù)開始執(zhí)行颤枪,當(dāng)一個線程的入口函數(shù)執(zhí)行完畢,線程就會被操作系統(tǒng)回收淑际;
隱式創(chuàng)建一條新的線程:
[self performSelectorInBackground:<#(nonnull SEL)#> withObject:<#(nullable id)#>];
線程間通訊(傳值)畏纲,不允許子線程中刷新UI
[self performSelectorOnMainThread:<#(nonnull SEL)#> withObject:<#(nullable id)#> waitUntilDone:<#(BOOL)#>];
實(shí)例方法創(chuàng)建一個子線程,需要手動開啟
NSThread *thread = [NSThread alloc] initWithTarget:<#(nonnull id)#> selector:<#(nonnull SEL)#> object:<#(nullable id)#>];
thread.name = @"子線程";
//啟動線程
[thread start];
類方法開啟一條新的線程春缕,不需要手動開啟盗胀,會直接執(zhí)行方法
[NSThread detachNewThreadSelector:<#(nonnull SEL)#> toTarget:<#(nonnull id)#> withObject:<#(nullable id)#>];
其中參數(shù):
/**
*? detachNewThreadSelector 創(chuàng)建一個線程并自動執(zhí)行
*? SEL:線程的入口函數(shù)
*? target:目標(biāo),在嗎哥object的selector上作為線程的入口函數(shù)
*? withObject:可以傳遞一個參數(shù)作為線程的參數(shù)
*
*/
/**
*? 操作系統(tǒng)給線程分配CPU的參考因素:
*? 1锄贼、時間片
*? 2票灰、優(yōu)先級
*? 3、線程的饑渴狀態(tài)
*? 4宅荤、線程nice值等
*? 注意:不是優(yōu)先級高就一定優(yōu)先執(zhí)行屑迂,CPU的調(diào)度室操作系統(tǒng)自己決定的,但是只要有一個線程冯键,CPU就會分配
*/
GCD:
GCD:是iOS提供的對多核并發(fā)支持的一種多線程技術(shù)之一惹盼,NSOperation就是使用GCD來實(shí)現(xiàn),GCD是以C語言的方式提供的琼了,需要我們一block的形式提供服務(wù)逻锐;
CGD:默認(rèn)是我們踢狗3中隊(duì)列供我們使用,分別是主隊(duì)列雕薪、全局并行隊(duì)列昧诱、串行隊(duì)列,我們只需要把我們的任務(wù)一block的形式提交到隊(duì)列上
任務(wù) && 隊(duì)列
任務(wù):同步(不開線程)和異步(開線程)
同步任務(wù)
dispatch_sync(<#dispatch_queue_t queue#>, <#^(void)block#>)
異步任務(wù)
dispatch_async(<#dispatch_queue_t queue#>, <#^(void)block#>)
隊(duì)列:串行(一個一個執(zhí)行)和并行(一起執(zhí)行)
1所袁、主隊(duì)列:主線程隊(duì)列盏档,在該隊(duì)列中放置所有任務(wù)都在主線程執(zhí)行,
2燥爷、全局并行隊(duì)列:在隊(duì)列上提交每個人物蜈亩,都是生成一個線程懦窘,并行的執(zhí)行,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
3稚配、串行隊(duì)列:在該隊(duì)列上提交的任務(wù)畅涂,生成一個線程,在該線程上順序執(zhí)行道川,一個執(zhí)行完成后下一個才能執(zhí)行,
dispatch_queue_create(<#const char *label#>, <#dispatch_queue_attr_t attr#>)
主隊(duì)列午衰,不允許在主線程中提交同步任務(wù),否則會死循環(huán)冒萄;dispatch_queue_t mainQueue = dispatch_get_main_queue();
同步:會卡死
異步:不會開線程臊岸,順序執(zhí)行
全局并發(fā)隊(duì)列
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT , 0);
同步:不會開線程,順序執(zhí)行尊流;
異步:會開線程帅戒,并且亂序執(zhí)行
自定義串行隊(duì)列
dispatch_queue_t SerialQueue = dispatch_queue_create("qf", NULL);
同步:不會開線程,順序執(zhí)行
異步:會開線程崖技,順序執(zhí)行
自定義并行隊(duì)列
dispatch_queue_t ConcurrentQueue = dispatch_queue_create("qf", DISPATCH_QUEUE_CONCURRENT);
同步:不會開線程逻住,順序執(zhí)行
異步:會開線程,亂序執(zhí)行
從子線程切換到主線程的方法
1响疚、self performSelectorOnMainThread:<#(nonnull SEL)#> withObject:<#(nullable id)#>
waitUntilDone:<#(BOOL)#>
2鄙信、[NSOperationQueue mainQueue] addOperation:<#(nonnull NSOperation *)#>
3、dispatch_async(<#dispatch_queue_t queue#>, <#^(void)block#>)