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