1.iOS的三種多線程技術(shù)
- 1.NSThread 每個(gè)NSThread對象對應(yīng)一個(gè)線程,量級(jí)較輕(真正的多線程)
- 2.以下兩點(diǎn)是蘋果專門開發(fā)的“并發(fā)”技術(shù),使得程序員可以不再去關(guān)心線程的具體使用問題
- NSOperation/NSOperationQueue 面向?qū)ο蟮木€程技術(shù)
- GCD —— Grand Central Dispatch(派發(fā)) 是基于C語言的框架,可以充分利用多核,是蘋果推薦使用的多線程技術(shù)
<p>以上這三種編程方式從上到下,抽象度層次是從低到高的,抽象度越高的使用越簡單,也是Apple最推薦使用的,在項(xiàng)目中很多框架技術(shù)分別使用了不同多線程技術(shù)。</p>
2.三種多線程技術(shù)的對比
NSThread:
優(yōu)點(diǎn):NSThread 比其他兩個(gè)輕量級(jí),使用簡單
缺點(diǎn):需要自己管理線程的生命周期、線程同步、加鎖、睡眠以及喚醒等。線程同步對數(shù)據(jù)的加鎖會(huì)有一定的系統(tǒng)開銷
NSOperation:
不需要關(guān)心線程管理,數(shù)據(jù)同步的事情,可以把精力放在自己需要執(zhí)行的操作上
NSOperation是面向?qū)ο蟮?/p>
GCD:
Grand Central Dispatch是由蘋果開發(fā)的一個(gè)多核編程的解決方案。iOS4.0+才能使用,是替代NSThread, NSOperation的高效和強(qiáng)大的技術(shù)
GCD是基于C語言的
3.三種多線程技術(shù)的實(shí)現(xiàn)
3.1 NSThread的多線程技術(shù)
- 類方法直接開啟后臺(tái)線程,并執(zhí)行選擇器方法:detachNewThreadSelector
<p>新建一個(gè)線程,調(diào)用@selector方法[NSThread detachNewThreadSelector:@selector(bigDemo) toTarget:self withObject:nil];</p> - 成員方法,在實(shí)例化線程對象之后,需要使用start執(zhí)行選擇器方法:initWithTarget
<p>成員方法 NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(bigDemo) object:nil]; // 啟動(dòng)start線程 [thread start];</p>
<p>對于NSThread的簡單使用,可以用NSObject的performSelectorInBackground替代</p>
<p>performSelectorInBackground是將bigDemo的任務(wù)放在后臺(tái)線程中執(zhí)行, [self performSelectorInBackground:@selector(bigDemo) withObject:nil];</p>
<p> 同時(shí),在NSThread調(diào)用的方法中,同樣要使用autoreleasepool進(jìn)行內(nèi)存管理,否則容易出現(xiàn)內(nèi)存泄露</p>
3.2 NSOperation,面向?qū)ο蟮亩嗑€程技術(shù)
- 使用步驟:
<p>實(shí)例化操作</p>
<p>實(shí)例化操作隊(duì)列 _queue = [[NSOperationQueue alloc] init];</p>
<p>實(shí)例化操作 NSInvocationOperation</p>
NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(opAction) object:nil];
// 如果使用start,會(huì)在當(dāng)前線程啟動(dòng)操作
// [op1 start];
// 一旦將操作添加到操作隊(duì)列,操作就會(huì)啟動(dòng)7
[_queue addOperation:op1];
<p>實(shí)例化操作 NSBlockOperation</p>
#pragma mark 模仿下載網(wǎng)絡(luò)圖像
- (IBAction)operationDemo3:(id)sender {
// 1. 下載
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下載 %@" , [NSThread currentThread]);
}];
// 2. 濾鏡
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"濾鏡 %@" , [NSThread currentThread]);
}];
// 3. 顯示
NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"更新UI %@" , [NSThread currentThread]);
}];
// 添加操作之間的依賴關(guān)系,所謂“依賴”關(guān)系,就是等待前一個(gè)任務(wù)完成后,后一個(gè)任務(wù)才能啟動(dòng)
// 依賴關(guān)系可以跨線程隊(duì)列實(shí)現(xiàn)
// 提示:在指定依賴關(guān)系時(shí),注意不要循環(huán)依賴,否則不工作。
[op2 addDependency:op1];
[op3 addDependency:op2];
[op1 addDependency:op3];
[_queue addOperation:op1];
[_queue addOperation:op2];
[[NSOperationQueue mainQueue] addOperation:op3];
}
<p> 將操作添加到隊(duì)列NSOperationQueue即可啟動(dòng)多線程執(zhí)行</p>
[_queue addOperation:op1];
[_queue addOperation:op2];
<p> 更新UI使用主線程隊(duì)列</p>
//兩方式 [NSOpeationQueue mainQueue] addOperation ^{
};
[[NSOperationQueue mainQueue] addOperation:op3];
<p> 操作隊(duì)列的setMaxConcurrentOperationCount:可以設(shè)置同時(shí)并發(fā)的線程數(shù)量!</p>
<p>控制同時(shí)最大并發(fā)的線程數(shù)量2 [_queue setMaxConcurrentOperationCount:2];</p>
<p>提示:此功能僅有NSOperation有!</p>
<p>使用addDependency可以設(shè)置任務(wù)的執(zhí)行先后順序,同時(shí)可以跨操作隊(duì)列指定依賴關(guān)系</p>
// 添加操作之間的依賴關(guān)系,所謂“依賴”關(guān)系,就是等待前一個(gè)任務(wù)完成后,后一個(gè)任務(wù)才能啟動(dòng)
// 依賴關(guān)系可以跨線程隊(duì)列實(shí)現(xiàn)
// 提示:在指定依賴關(guān)系時(shí),注意不要循環(huán)依賴,否則不工作。
[op2 addDependency:op1];
[op3 addDependency:op2];
[op1 addDependency:op3];
提示:在指定依賴關(guān)系時(shí),注意不要循環(huán)依賴,否則不工作。
3.3. GCD,C語言
GCD就是為了在“多核”上使用多線程技術(shù)
要使用GCD,所有的方法都是dispatch開頭的
-
名詞解釋
- global 全局
- queue 隊(duì)列
- async 異步
- sync 同步
要執(zhí)行異步的任務(wù),就在全局隊(duì)列中執(zhí)行即可,dispatch_async 異步執(zhí)行控制不住先后順序
<p> 關(guān)于GCD的隊(duì)列</p>全局隊(duì)列 dispatch_get_global_queue</p>
<p>參數(shù):優(yōu)先級(jí) DISPATCH_QUEUE_PRIORITY_DEFAULT, 始終是 0</p>
<p> dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 可同步 可異步</p>串行隊(duì)列
<p>dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);是創(chuàng)建得到的,不能直接獲取只能同步</p>主隊(duì)列 dispatch_get_main_queue
<p>
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"main - > %@", [NSThread currentThread]);
});只能同歩
</p>異步和同步與方法名無關(guān),與運(yùn)行所在的隊(duì)列有關(guān)!同步主要用來控制方法的被調(diào)用的順序