http://blog.csdn.net/totogo2010/article/details/9816975程就是一個獨立的執(zhí)行路徑
多線程技術(shù)的優(yōu)勢肘迎、弊端
優(yōu)勢
(1)充分發(fā)揮多核處理器優(yōu)勢,將不同線程任務(wù)分配給不同的處理器,真正進入“并行運算”狀態(tài)
(2)將耗時的任務(wù)分配到其他線程執(zhí)行,由主線程負責(zé)統(tǒng)一更新界面會使應(yīng)用程序更加流暢,用戶體驗更好
(3)當(dāng)硬件處理器的數(shù)量增加,程序會運行更快,而程序無需做任何調(diào)整
(4)并發(fā)編程 為了讓程序員從負責(zé)線程控制中解脫出來,只需要面對隊列和任務(wù)
弊端
新建線程會消耗內(nèi)存空間和 CPU 時間,線程太多會降低系統(tǒng)的運行性能
?NSThread
?NSOperation/NSOperationQueue
?GCD
1、什么是GCD Grand Central Dispath
?GCD是基于C語言的底層API,用Block定義任務(wù)
?GCD的有四種隊列,一是串行隊列旱爆、二是并行隊列笋轨、全局隊列、主隊列
?GCD的操作有兩種,一是異步操作衩侥、二是同步操作
串行隊列 + 同步任務(wù) a.任務(wù)會在當(dāng)線程中執(zhí)行 當(dāng)是主線程時會阻塞當(dāng)線程 b.在開發(fā)中很少用
串行隊列 + 異步任務(wù) >任務(wù)的執(zhí)行是順序執(zhí)行>任務(wù)執(zhí)行的線程:是在新的線程里執(zhí)行
并行隊列 + 同步任務(wù) 并行隊列借尿,如果在同步任務(wù)執(zhí)行刨晴,隊列里的任務(wù)是順序執(zhí)行
并行隊列 + 異步任務(wù) 1.不能指定隊列任務(wù)執(zhí)行的順序 2.不能控制線程開啟的數(shù)據(jù) 隨機的,為大多數(shù)任務(wù)開啟子線程
全局隊列 + 異步任務(wù) 全局隊列就是并行隊列,全局隊列里任務(wù)執(zhí)行順序是隨機
全局隊列 是由系統(tǒng)提供的隊列,不需要程序員創(chuàng)建,全局隊列是一個設(shè)備上所有APP共享的路翻。
串行隊列+ 同步嵌+套同步 會造成阻塞 原因 任務(wù)1里 嵌套 任務(wù)2 按代碼順序看 執(zhí)行任務(wù) 1時 里面有個任務(wù) 2 因為 是同步 要執(zhí)行完任務(wù)1 才能 2 但1都沒執(zhí)行完又要2
主隊列 + 同步 會造成阻塞 原因:同步要等主隊列里第一個任務(wù)完成后才會執(zhí)行后面的任務(wù),如當(dāng)前主隊列有個初始化和顯示UI的任務(wù),并且主隊列是串行隊列狈癞。
創(chuàng)建隊列 :
串行隊列的創(chuàng)建:
dispatch_queue_t q =
dispatch_queue_create("cn.gzitcast", DISPATCH_QUEUE_SERIAL);
并行隊列的創(chuàng)建:
dispatch_queue_t q =
dispatch_queue_create("cn.gzitcast.cn", DISPATCH_QUEUE_CONCURRENT);
全局隊列的創(chuàng)建:
dispatch_queue_t q =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
主隊列的創(chuàng)建:
dispatch_queue_t q = dispatch_get_main_queue();
同步任務(wù)的執(zhí)行:
dispatch_sync(q, ^{
執(zhí)行的內(nèi)容
});
異步任務(wù)的執(zhí)行:
dispatch_async(q, ^{
執(zhí)行的內(nèi)容
});
// 一次性執(zhí)行:
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// code to be executed once
});
// 延遲2秒執(zhí)行:
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
// code to be executed on the main queue after delay
});
// 自定義dispatch_queue_t
dispatch_queue_t urls_queue = dispatch_queue_create("blog.devtang.com", NULL);
dispatch_async(urls_queue, ^{
// your code
});
dispatch_release(urls_queue);
// 合并匯總結(jié)果
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{
// 并行執(zhí)行的線程一
});
dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{
// 并行執(zhí)行的線程二
});
dispatch_group_notify(group, dispatch_get_global_queue(0,0), ^{
// 匯總結(jié)果
});
dispatch_barrier_async的使用
dispatch_barrier_async是在前面的任務(wù)執(zhí)行結(jié)束后它才執(zhí)行,而且它后面的任務(wù)等它執(zhí)行完成之后才會執(zhí)行
dispatch_queue_t queue = dispatch_queue_create("gcdtest.rongfzh.yc", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"dispatch_async1");
});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:4];
NSLog(@"dispatch_async2");
});
dispatch_barrier_async(queue, ^{
NSLog(@"dispatch_barrier_async");
[NSThread sleepForTimeInterval:4];
});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"dispatch_async3");
});
4茂契、dispatch_apply
執(zhí)行某個代碼片段N次蝶桶。
dispatch_apply(5, globalQ, ^(size_t index) {
// 執(zhí)行5次
});
1.什么是NSOperation & NSOperationQueue
?操作【也就是任務(wù)】和操作隊列
?NSOperation & NSOperationQueue【操作隊列】是由GCD提供的隊列模型的Cocoa抽象,是一套Object-C的API
?或者話說NSOperation & NSOperationQueue是對GCD的封閉掉冶,是開發(fā)者的最好選擇
2.NSOperationQueue操作隊列有哪些
?NSOperationQueue有兩種不同的類型的隊列:主隊列和自定義隊列
?主隊列運行在主線程上
?自定義隊列在后臺執(zhí)行
?隊列的處理任務(wù)是NSOperation的子類
1)NSInvocationOperation
2)NSBlockOperation
3.NSOperation & NSOperationQueue使用步驟
1).定義操作隊列
2).定義操作【也就是任務(wù)】
3).將操作添加到隊列中
提示:一旦將操作添加到隊列中真竖,操作就會馬上執(zhí)行
-(void)demo1{
//1.創(chuàng)建操作隊列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//2.創(chuàng)建任務(wù)
//2.1使用NSBlockOperation定義一個任務(wù)
NSBlockOperation *op1 = [[NSBlockOperation alloc] init];
[op1 addExecutionBlock:^{
NSLog(@"任務(wù)1 %@",[NSThread currentThread]);
}];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"任務(wù)2 %@",[NSThread currentThread]);
}];
//2.2使用NSInvocationOperation定義任務(wù)
NSInvocationOperation *op3 = [[NSInvocationOperation alloc]
initWithTarget:self selector:@selector(operation3) object:nil];
//傳參
NSInvocationOperation *op4 = [[NSInvocationOperation alloc]
initWithTarget:self selector:@selector(operation4:) object:@"任務(wù)4"];
//3.任務(wù)添加到隊列
[queue addOperation:op1];
[queue addOperation:op2];
[queue addOperation:op3];
[queue addOperation:op4];
/*總結(jié)
*1.每次線程執(zhí)行的順序不同
*2.操作任務(wù)添加到操作隊列后就會馬上執(zhí)行
*3.自定義隊列里的任務(wù)會在子線程里執(zhí)行
*/
}
案例:主隊列
-(void)demo2{
//1.獲取主隊列
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
//2.定義任務(wù)
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"UI更新%@",[NSThread currentThread]);
}];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"UI2更新%@",[NSThread currentThread]);
}];
//3.任務(wù)添加到隊列
[mainQueue addOperation:op1];
[mainQueue addOperation:op2];
}
4.操作隊列間的依賴
eg:圖片下載 -》 圓角 -》 保存 -》刷新主線程
添加依賴調(diào)用"操作[NSOperation]"的addOperation方法
-(void)demo3{
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下載圖片%@",[NSThread currentThread]);
}];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"修飾圖片%@",[NSThread currentThread]);
}];
NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"保存圖片%@",[NSThread currentThread]);
}];
NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"刷新UI %@",[NSThread currentThread]);
}];
// 添加依賴
[op2 addDependency:op1];
[op3 addDependency:op2];
[op4 addDependency:op3];
[self.queue addOperation:op1];
[self.queue addOperation:op2];
[self.queue addOperation:op3];
[[NSOperationQueue mainQueue] addOperation:op4];
}
5.設(shè)置并發(fā)數(shù)
?線程的創(chuàng)建是要開銷內(nèi)存 CPU 電量!
?應(yīng)用中:下載圖片 使用并發(fā)線程 如果線程的工作結(jié)束 沒銷毀 厌小,會新建線程
?線程數(shù)使用原則
1)在3G / 4G: 開3個線程
2)在Wifi: 開6個線程
?設(shè)置任務(wù)并發(fā)個數(shù)[隊列 setMaxConcurrentOperationCount:3];
-(void)demo4{
//設(shè)置并發(fā)線程數(shù)
[self.queue setMaxConcurrentOperationCount:5];
for (int i = 0; i < 20; i++) {
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下載圖片%d %@",i,[NSThread currentThread]);
}];
[self.queue addOperation:op1];
}
}