1. iOS三種多線程技術(shù)
- NSThread每個NSThread對象對應(yīng)一個線程,量級較輕(真正的多線程)
- NSOperation/NSOperationQueue 面向?qū)ο蟮木€程技術(shù)
- GCD —— Grand Central Dispatch(派發(fā)) 是基于C語言的框架染坯,可以充分利用多核均芽,是蘋果推薦使用的多線程技術(shù)
- (后兩點是蘋果專門開發(fā)的“并發(fā)”技術(shù),使得程序員可以不再去關(guān)心線程的具體使用問題)
以上這三種編程方式從上到下单鹿,抽象度層次是從低到高的掀宋,抽象度越高的使用越簡單,也是Apple最推薦使用的仲锄,在項目中很多框架技術(shù)分別使用了不同多線程技術(shù)劲妙。
2. 三種多線程技術(shù)的對比
- NSThread:
–優(yōu)點:NSThread 比其他兩個輕量級,使用簡單
–缺點:需要自己管理線程的生命周期昼窗、線程同步是趴、加鎖、睡眠以及喚醒等澄惊。線程同步對數(shù)據(jù)的加鎖會有一定的系統(tǒng)開銷 - NSOperation:
–不需要關(guān)心線程管理唆途,數(shù)據(jù)同步的事情,可以把精力放在自己需要執(zhí)行的操作上
–NSOperation是面向?qū)ο蟮?/li> - GCD:
–Grand Central Dispatch是由蘋果開發(fā)的一個多核編程的解決方案掸驱。iOS4.0+才能使用肛搬,是替代NSThread, NSOperation的高效和強(qiáng)大的技術(shù)
–GCD是基于C語言的
3. 三種多線程的技術(shù)實現(xiàn)
-
NSThread的技術(shù)實現(xiàn):
1> 類方法直接開啟后臺線程毕贼,并執(zhí)行選擇器方
detachNewThreadSelector
// 新建一個線程温赔,調(diào)用@selector方法
[NSThread detachNewThreadSelector:@selector(bigDemo) toTarget:self withObject:nil];
2>成員方法,在實例化線程對象之后鬼癣,需要使用start執(zhí)行選擇器方法
initWithTarget
// 成員方法
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(bigDemo) object:nil];
// 啟動start線程
[thread start];
對于NSThread的簡單使用陶贼,可以用NSObject的performSelectorInBackground替代
// performSelectorInBackground是將bigDemo的任務(wù)放在后臺線程中執(zhí)行
[self performSelectorInBackground:@selector(bigDemo) withObject:nil];
同時啤贩,在NSThread調(diào)用的方法中,同樣要使用autoreleasepool進(jìn)行內(nèi)存管理拜秧,否則容易出現(xiàn)內(nèi)存泄露痹屹。
// 自動釋放池
// 負(fù)責(zé)其他線程上的內(nèi)存管理,在使用NSThread或者NSObject的線程方法時枉氮,一定要使用自動釋放池
// 否則容易出現(xiàn)內(nèi)存泄露志衍。
@autoreleasepool {
}
-
NSOperation,面向?qū)ο蟮亩嗑€程技術(shù)實現(xiàn):
1) 使用步驟:
1> 實例化操作:
1 // 實例化操作隊列
2 _queue = [[NSOperationQueue alloc] init];
之后:
a) NSInvocationOperation (舊)
1 NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(opAction) object:nil];
2
3 // 如果使用start,會在當(dāng)前線程啟動操作
4 // [op1 start];
5
6 // 1. 一旦將操作添加到操作隊列聊替,操作就會啟動
7 [_queue addOperation:op1];
b) NSBlockOperation (新)
1 #pragma mark 模仿下載網(wǎng)絡(luò)圖像
2 - (IBAction)operationDemo3:(id)sender
3 {
4 // 1. 下載
5 NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
6 NSLog(@"下載 %@" , [NSThread currentThread]);
7 }];
8 // 2. 濾鏡
9 NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
10 NSLog(@"濾鏡 %@" , [NSThread currentThread]);
11 }];
12 // 3. 顯示
13 NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
14 NSLog(@"更新UI %@" , [NSThread currentThread]);
15 }];
16
17 // 添加操作之間的依賴關(guān)系楼肪,所謂“依賴”關(guān)系,就是等待前一個任務(wù)完成后惹悄,后一個任務(wù)才能啟動
18 // 依賴關(guān)系可以跨線程隊列實現(xiàn)
19 // 提示:在指定依賴關(guān)系時春叫,注意不要循環(huán)依賴,否則不工作俘侠。
20 [op2 addDependency:op1];
21 [op3 addDependency:op2];
22 // [op1 addDependency:op3];
23
24 [_queue addOperation:op1];
25 [_queue addOperation:op2];
26 [[NSOperationQueue mainQueue] addOperation:op3];
27 }
2> 將操作添加到隊列NSOperationQueue即可啟動多線程執(zhí)行
1 [_queue addOperation:op1];
2 [_queue addOperation:op2];
2 ) 更新UI使用主線程隊列
//兩方式
[NSOpeationQueue mainQueue] addOperation ^{
};
[[NSOperationQueue mainQueue] addOperation:op3];
3 ) 操作隊列的setMaxConcurrentOperationCount 可以設(shè)置同時并發(fā)的線程數(shù)量
1 // 控制同時最大并發(fā)的線程數(shù)量
2 [_queue setMaxConcurrentOperationCount:2];
提示:此功能僅有NSOperation有象缀!
4 ) 使用addDependency可以設(shè)置任務(wù)的執(zhí)行先后順序,同時可以跨操作隊列指定依賴關(guān)系
1 // 添加操作之間的依賴關(guān)系爷速,所謂“依賴”關(guān)系央星,就是等待前一個任務(wù)完成后,后一個任務(wù)才能啟動
2
3 // 依賴關(guān)系可以跨線程隊列實現(xiàn)
4
5 // 提示:在指定依賴關(guān)系時惫东,注意不要循環(huán)依賴莉给,否則不工作。
6 [op2 addDependency:op1];
7 [op3 addDependency:op2];
8 [op1 addDependency:op3];
提示:在指定依賴關(guān)系時廉沮,注意不要循環(huán)依賴颓遏,否則不工作。
- GCD 技術(shù)實現(xiàn)滞时, C語言
GCD就是為了在“多核”上使用多線程技術(shù)
1> 要使用GCD叁幢,所有的方法都是dispatch開頭的
2> 名詞解釋
global 全局
queue 隊列
async 異步
sync 同步
3> 要執(zhí)行異步的任務(wù),就在全局隊列中執(zhí)行即可
dispatch_async 異步執(zhí)行控制不住先后順序
4> 關(guān)于GCD的隊列
- 全局隊列(并發(fā)隊列):dispatch_get_global_queue
Concurrent queue(global dispatch queue):
參數(shù):優(yōu)先級 DISPATCH_QUEUE_PRIORITY_DEFAULT
始終是 0
1 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
(可同步 可異步)
- 串行隊列:Serial quque(private dispatch queue)
dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
是創(chuàng)建得到的坪稽,不能直接獲取
只能同步
- 主隊列: dispatch_get_main_queue
1 dispatch_async(dispatch_get_main_queue(), ^{
2 NSLog(@"main - > %@", [NSThread currentThread]);
3 });
5> 異步和同步與方法名無關(guān)曼玩,與運(yùn)行所在的隊列有關(guān)!
同步主要用來控制方法的被調(diào)用的順序