多線程 Nsthread GCD 和 Nsopration 的用法

一? pthread :?

/*

參數(shù):

1.線程代號的地址

2.線程的屬性

3.調(diào)用函數(shù)的指針

4.傳遞給函數(shù)的參數(shù)

返回值:

- 如果是 0, 表示正確

- 如果是非0,表示錯誤碼

void *--(*)--(void *)

返回值--(函數(shù)指針)--(參數(shù))

void *? 相當(dāng)于 OC中的id

*/

-(void)pthreadDemo{

pthread_t threadID;

NSString * str = @"hello 老王";

/*

- 在 ARC 開發(fā)中, 如果遇到 OC和C 語言中相同數(shù)據(jù)類型進(jìn)行轉(zhuǎn)換,需要使用__bridge "橋接"

- 在 MRC 開發(fā)中,不需要橋接

在 OC 中,如果是ARC開發(fā),編譯器會在編譯的時(shí)候,自動根據(jù)代碼結(jié)構(gòu),添加 retain , release, autorelease

ARC 只負(fù)責(zé) OC部分的代碼,不負(fù)責(zé)C的代碼. 如果C的代碼里面出現(xiàn)了 retain/create/copy 字樣的函數(shù),都需要release

*/

int result = pthread_create(&threadID, NULL, &demo, (__bridge void *)(str));

if (result == 0) {

for (int i? = 0; i < 20; i++) {

NSLog(@"OK!");

}

}else{

NSLog(@"error %d",result);

}

}

void * demo(void *param){

NSString * sss = (__bridge NSString *)(param);

NSLog(@"%@---%@",[NSThread currentThread],sss);

return NULL;

}

一 ?NSThread

oc語言需要程序員手動管理線程

//創(chuàng)建線程 開辟一個(gè)子線程 常用創(chuàng)建方法

?1 ?NSThread * thread = [[NSThread alloc]initWithTarget:self selector:@selector(demo:) object:@"thread"];

//啟動線程

[thread start];

//創(chuàng)建以后立即開啟

2 ?[NSThread detachNewThreadSelector:@selector(demo:) toTarget:self withObject:@"Detach"];

//常用的方法

3 ? [self performSelectorInBackground:@selector(longOperation) withObject:nil];

延時(shí)操作

[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];

[NSThread sleepForTimeInterval:2.0];

殺死線程

//一旦強(qiáng)行終止線程,后續(xù)的所有的代碼都不會執(zhí)行

//注意:在終止線程之前,應(yīng)該注意釋放之前分配的對象!否則出現(xiàn)內(nèi)存泄露!

?4 ?[NSThread exit];


二 優(yōu)先級屬性

/*優(yōu)先級

* 優(yōu)先級只能保證 CPU 調(diào)度的可能性會高!

* 多線程的目的: 將耗時(shí)的操作放在后臺,不阻塞主線程和用戶的交互!

* 建議: 盡量不要修改 優(yōu)先級!

* "優(yōu)先級翻轉(zhuǎn)"

* 在多線程開發(fā)中,不要相信你看到的結(jié)果!!一定要理性的(冷靜)分析!!

*/

t2.threadPriority = 0.1;

三 ?資源共享

@synchronized

//參數(shù):就是能夠加鎖的任意 NSOjbect 對象

//局部變量: 每個(gè)線程單獨(dú)擁有的,無法鎖住!!

//注意: 鎖一定要是所有線程共享的對象!!

@synchronized (<#token#>) {

<#statements#>

//互斥鎖 - 保證鎖內(nèi)的代碼,同一時(shí)間,只有一條線程能夠執(zhí)行!!

//互斥鎖它的范圍,應(yīng)該盡量小,鎖范圍越大,效率越低!

}

三 GCD 相關(guān)用法

1. 什么是GCD

全稱是Grand Central Dispatch,可譯為“牛逼的中樞調(diào)度器”

純C語言,提供了非常多強(qiáng)大的函數(shù)

2. GCD的優(yōu)勢

GCD是蘋果公司為多核的并行運(yùn)算提出的解決方案

GCD會自動利用更多的CPU內(nèi)核(比如雙核险污、四核 為以后蘋果公司推出多核提供兼容)

GCD會自動管理線程的生命周期(創(chuàng)建線程、調(diào)度任務(wù)、銷毀線程)

程序員只需要告訴GCD想要執(zhí)行什么任務(wù)太颤,不需要編寫任何線程管理代碼

3.GCD中有2個(gè)核心概念

任務(wù):執(zhí)行什么操作

隊(duì)列:用來存放任務(wù)

GCD的使用就2個(gè)步驟

定制任務(wù)

確定想做的事情

將任務(wù)添加到隊(duì)列中

GCD會自動將隊(duì)列中的任務(wù)取出,放到對應(yīng)的線程中執(zhí)行

任務(wù)的取出遵循隊(duì)列的FIFO原則:先進(jìn)先出纯衍,后進(jìn)后出

4 GCD常用方法

1. 延時(shí)操作

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(<#delayInSeconds#> * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

});

2 一次執(zhí)行操作(設(shè)置單列的時(shí)候經(jīng)常用到)

//GCD提供了一個(gè)一次執(zhí)行的機(jī)制,不僅能夠保證只會被執(zhí)行一次.而且是線程安全的!

//GCD-Once 內(nèi)部是會加鎖!! 但是 比普通的互斥鎖 效率高 100多倍 蘋果推薦使用這個(gè)

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

});

3 調(diào)度組?

//MARK: 調(diào)度組

-(void)group1{

//1.隊(duì)列

dispatch_queue_t q = dispatch_get_global_queue(0, 0);

//2.調(diào)度組

dispatch_group_t g = dispatch_group_create();

//3.添加任務(wù),讓隊(duì)列執(zhí)行,任務(wù)執(zhí)行情況最終通知組

dispatch_group_async(g, q, ^{

NSLog(@"download A %@",[NSThread currentThread]);

});

dispatch_group_async(g, q, ^{

[NSThread sleepForTimeInterval:1.0];

NSLog(@"download B %@",[NSThread currentThread]);

});

dispatch_group_async(g, q, ^{

[NSThread sleepForTimeInterval:0.8];

NSLog(@"download C %@",[NSThread currentThread]);

});

//4. 所有任務(wù)執(zhí)行完畢后,獲得通知

//用一個(gè)調(diào)度組,可以監(jiān)聽全局隊(duì)列調(diào)度的任務(wù),執(zhí)行完畢之后,在主隊(duì)列執(zhí)行最終處理!

//dispatch_group_notify 本身是異步的

dispatch_group_notify(g, dispatch_get_main_queue(), ^{

//更新UI,通知用戶

NSLog(@"OK? %@",[NSThread currentThread]);

});

NSLog(@"come here");

}

//MARK: 主隊(duì)列,同步任務(wù)

//阻塞主線程!!

-(void)gcdDemo2{

//1.隊(duì)列? -> 一啟動就有主線程,主隊(duì)列只需要獲取

dispatch_queue_t q = dispatch_get_main_queue();

NSLog(@"這里!!");

//2.同步任務(wù)

dispatch_sync(q, ^{

NSLog(@"能來嗎?");

});

NSLog(@"come here -- %@",[NSThread currentThread]);

}

5 GCD總結(jié)

/**

GCD 核心概念:將任務(wù)添加到隊(duì)列,指定任務(wù)執(zhí)行的方法

- 任務(wù)

- 使用block 封裝

- block就是一個(gè)提前準(zhǔn)備好的代碼塊,在需要的時(shí)候執(zhí)行

- 隊(duì)列(負(fù)責(zé)調(diào)度任務(wù))

- 串行隊(duì)列:一個(gè)接一個(gè)的調(diào)度任務(wù)

- 并發(fā)對象:可以同時(shí)調(diào)度多個(gè)任務(wù)

- 執(zhí)行任務(wù)的函數(shù)

- 同步執(zhí)行: 當(dāng)前指令不完成,就不會執(zhí)行下一條指令

- 異步執(zhí)行: 當(dāng)前執(zhí)行不完成,同樣可以執(zhí)行下一條指令

小結(jié):

- 開不開線程,取決于同步\異步. 同步,不開!? 異步,開!

- 開多少條線程,取決于隊(duì)列,串行開一條,并發(fā)(異步)開多條!

hank:開啟子線程只能是異步!!!? 線程多開\并發(fā)且異步

只要是異步就開啟子線程!!!

全局隊(duì)列 & 并發(fā)隊(duì)列

1. 名稱,并發(fā)隊(duì)列有名稱,適合大型項(xiàng)目跟蹤錯誤報(bào)告!

2. release,在 MRC 開發(fā)時(shí),并發(fā)隊(duì)列需要使用 dispatch_release(q);

結(jié)論:目前絕大多數(shù)軟件都會使用全局隊(duì)列.

全局隊(duì)列 & 串行隊(duì)列

全局隊(duì)列(并發(fā)): 并發(fā),能夠調(diào)度多個(gè)線程,執(zhí)行效率高!!!

- 費(fèi)電!!

串行隊(duì)列: 一個(gè)接一個(gè),只能開啟一條線程,執(zhí)行效率低!!

- 省電,省錢,省流量

選擇的依據(jù): 根據(jù)用戶的上網(wǎng)方式!!

- WIFI ,可以開多條線程, 6條

- 3G\4G,盡量少開線程,2~3 條

四 ?NSOperation

特點(diǎn): ? 不能直接使用

目的: ?定義子類中共有的屬性和方法

子類:- NSInvocationOperation ? ?- NSBlockOperation

1. ? 創(chuàng)建 ? //? ? NSInvocationOperation 操作

NSInvocationOperation * op = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downloadImage:) object:@"Hank"];

//start 方法,會在當(dāng)前線程執(zhí)行調(diào)度方法

//? ? [op start];

//1.隊(duì)列

NSOperationQueue * q = [[NSOperationQueue alloc]init];

//2.將操作添加到隊(duì)列 - 會自動異步執(zhí)行調(diào)度方法

[q addOperation:op];

2. ? ?//NSBlockOperation 所有的代碼都寫在一起.更加好維護(hù)

NSOperationQueue * q = [[NSOperationQueue alloc]init];

NSBlockOperation * op = [NSBlockOperation blockOperationWithBlock:^{

NSLog(@"%@ ---- %d",[NSThread currentThread],i);

}];

[q addOperation:op];

二 ?線程間的通訊

[self.opQueue addOperationWithBlock:^{

NSLog(@"耗時(shí)操作!! %@",[NSThread currentThread]);

//主線程 更新UI ,主隊(duì)列

[[NSOperationQueue mainQueue] addOperationWithBlock:^{

NSLog(@"UIUIUI --- %@",[NSThread currentThread]);

}];

}];

三 ?依賴關(guān)系

/**

需求:從網(wǎng)上下載視頻\完成之后解碼\通知用戶

*/

//1.下載

NSBlockOperation * op1 = [NSBlockOperation blockOperationWithBlock:^{

[NSThread sleepForTimeInterval:3.0];

NSLog(@"下載? -? %@",[NSThread currentThread]);

}];

//2.解碼

NSBlockOperation * op2 = [NSBlockOperation blockOperationWithBlock:^{

[NSThread sleepForTimeInterval:2.0];

NSLog(@"解碼? -? %@",[NSThread currentThread]);

}];

//3.通知用戶

NSBlockOperation * op3 = [NSBlockOperation blockOperationWithBlock:^{

NSLog(@"通知用戶? -? %@",[NSThread currentThread]);

}];

//NSOperation 提供了依賴關(guān)系

//NSOperation 的所有的操作都是異步執(zhí)行的,但是為了建立任務(wù)之間的依賴,提供了dependency的功能

//GCD中,通過同步任務(wù)來實(shí)現(xiàn),也可以通過串行隊(duì)列!

[op2 addDependency:op1];//op2 依賴于 op1? == op1 執(zhí)行完畢 op2 開始執(zhí)行

[op3 addDependency:op2];

// !!千萬注意!!!:? 不要循環(huán)依賴!!!!,一旦指定了循環(huán)依賴,隊(duì)列就不能執(zhí)行被循環(huán)依賴的操作了!!

//不會造成死鎖!? 但是 以前的版本 會死鎖!!

//? ? [op1 addDependency:op3];

[self.opQueue addOperations:@[op1,op2] waitUntilFinished:NO];

//主線程通知用戶

[[NSOperationQueue mainQueue] addOperation:op3];

NSLog(@"come here");

四 ?取消線程

//提示: 取消操作,同樣不會取消正在執(zhí)行中的操作

[self.opQueue cancelAllOperations];

五 暫停/恢復(fù)線程

//在設(shè)置隊(duì)列的暫停屬性時(shí),并不會判斷隊(duì)列中是否有操作!

//如果不希望用戶產(chǎn)生困惑,可以提前做判斷

//判斷隊(duì)列中當(dāng)前是否有操作

if (self.opQueue.operationCount == 0){

NSLog(@"沒有操作!!!");

return ;

}

if (self.opQueue.isSuspended) {

//在暫停的時(shí)候,隊(duì)列中的操作數(shù),是包含正在執(zhí)行的操作!!

NSLog(@"繼續(xù) %tu",self.opQueue.operationCount);

self.opQueue.suspended = NO;

}else{

//再次繼續(xù)運(yùn)行的時(shí)候,如果之前執(zhí)行的操作已經(jīng)完成,隊(duì)列中的操作數(shù)就只有未調(diào)度的了!!

NSLog(@"暫停 %tu",self.opQueue.operationCount);

self.opQueue.suspended = YES;

}

六 最大線程

//設(shè)置同時(shí)最大并發(fā)操作數(shù)量

//WIFI: 5~6

//2G/3G/4G: 2~3

self.opQueue.maxConcurrentOperationCount = 2;

//向隊(duì)列添加任務(wù)

//從 iOS 8.0 開始,無論使用GCD 還是 NSOperation, 都會開啟很多線程

//在 iOS 7.0 以前,GCD 通常只會開啟 5 ~ 6 條線程!

//目前線程數(shù)量多說明:

//1.底層的線程池更大了,能夠拿到的線程資源更多了!

//2.對控制同時(shí)并發(fā)的線程數(shù),要求就更高!

GCD和NSOpration的比較

/*

NSOperation 是蘋果公司大力推薦的"并發(fā)"技術(shù)! 開發(fā)者已經(jīng)不需要關(guān)心線程以及線程的生命周期!

,而且我們逃離了GCD的 并發(fā)還是串行 異步還是同步!

NSOperation 的核心概念: 將"操作" 添加到 "隊(duì)列"

GCD的核心概念: 將"任務(wù)"添加到隊(duì)列,指定任務(wù)的執(zhí)行函數(shù)(方法)

----------------------------------------------------------------------------------

GCD & NSOperation 的對比

GCD 在 iOS 4.0推出的,主要針對多核處理器做了優(yōu)化的并發(fā)技術(shù),是 C 語言!

- 將"任務(wù)"[block]"添加到"隊(duì)列[串行/并發(fā)/主隊(duì)列/全局],并且指定執(zhí)行任務(wù)的函數(shù)[同步/異步]

- 線程間的通訊 dispatch_get_main_queue()

- 提供了一些 NSOperation 不具備的功能

- 一次執(zhí)行(單例設(shè)計(jì)模式最常用)

- 延遲執(zhí)行

- 調(diào)度組

- 等等...

NSOperation 在 iOS 2.0 推出的!

- 將操作[異步執(zhí)行的任務(wù)] 添加到 隊(duì)列[并發(fā)隊(duì)列],就會立刻異步執(zhí)行

- mainQueue

- 提供了一些 GCD 實(shí)現(xiàn)起來比較困難的功能

- 最大并發(fā)線程數(shù)

- 隊(duì)列的暫停/繼續(xù)

- 取消所有操作

- 指定操作之間的依賴關(guān)系(GCD 同步實(shí)現(xiàn))

----------------------------------------------------------------------------------

NSOperation類是一個(gè)抽象類

特點(diǎn):

- 不能直接使用

目的:

- 定義子類中共有的屬性和方法

子類:

- NSInvocationOperation

- NSBlockOperation

*/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末栋齿,一起剝皮案震驚了整個(gè)濱河市苗胀,隨后出現(xiàn)的幾起案子襟诸,更是在濱河造成了極大的恐慌,老刑警劉巖基协,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件歌亲,死亡現(xiàn)場離奇詭異,居然都是意外死亡澜驮,警方通過查閱死者的電腦和手機(jī)陷揪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來杂穷,“玉大人悍缠,你說我怎么就攤上這事∧土浚” “怎么了飞蚓?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長廊蜒。 經(jīng)常有香客問我趴拧,道長溅漾,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任著榴,我火速辦了婚禮添履,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘脑又。我一直安慰自己暮胧,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布问麸。 她就那樣靜靜地躺著叔壤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪口叙。 梳的紋絲不亂的頭發(fā)上炼绘,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天,我揣著相機(jī)與錄音妄田,去河邊找鬼俺亮。 笑死,一個(gè)胖子當(dāng)著我的面吹牛疟呐,可吹牛的內(nèi)容都是我干的脚曾。 我是一名探鬼主播,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼启具,長吁一口氣:“原來是場噩夢啊……” “哼本讥!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起鲁冯,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤拷沸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后薯演,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體撞芍,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年跨扮,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了序无。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,505評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡衡创,死狀恐怖帝嗡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情璃氢,我是刑警寧澤哟玷,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站拔莱,受9級特大地震影響碗降,放射性物質(zhì)發(fā)生泄漏隘竭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一讼渊、第九天 我趴在偏房一處隱蔽的房頂上張望动看。 院中可真熱鬧,春花似錦爪幻、人聲如沸菱皆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽仇轻。三九已至,卻和暖如春奶甘,著一層夾襖步出監(jiān)牢的瞬間篷店,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工臭家, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留疲陕,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓钉赁,卻偏偏與公主長得像蹄殃,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子你踩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評論 2 359

推薦閱讀更多精彩內(nèi)容