為了方便測(cè)試踊淳,我們寫(xiě)一個(gè)耗時(shí)計(jì)算的方法:
-(void)calculateAction{
// 當(dāng)子線(xiàn)程中出現(xiàn)對(duì)象類(lèi)型時(shí)嗅虏,需要使用自動(dòng)釋放池包裹對(duì)應(yīng)的代碼
@autoreleasepool {
int sum = 0;
for (int i =0; i<655350000; i++) {
sum += i;
}
// 打印當(dāng)前方法是否為主線(xiàn)程
NSLog(@"===當(dāng)前線(xiàn)程A:%d",[NSThread isMainThread]);
// 打印當(dāng)前線(xiàn)程
NSLog(@"===當(dāng)前線(xiàn)程B:%@",[NSThread currentThread]);
NSLog(@"===結(jié)果:%d",sum);
}
}
1、NSThread
NSThread的創(chuàng)建:
NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(calculateAction) object:nil];
[thread start];
NSLog(@"===當(dāng)前線(xiàn)程%d",[NSThread isMainThread]);
NSLog(@"===當(dāng)前線(xiàn)程11:%@",[NSThread currentThread]);
[thread cancel];
這里然痊,我們可以看到輸出的結(jié)果是:耗時(shí)計(jì)算的方法是在子線(xiàn)程中執(zhí)行唉匾。
同時(shí)旦委,NSThread還包含isExecuting苇瓣、isCancelled屬性尉间,是否在執(zhí)行,是否取消執(zhí)行击罪。NSThread需要手動(dòng)開(kāi)啟哲嘲。
[NSThread sleepForTimeInterval:10];關(guān)于這個(gè)方法的用處,在融云SDK里發(fā)送多張圖片中用到過(guò)媳禁,在for循環(huán)中眠副,加入延時(shí)執(zhí)行代碼,在發(fā)送效果上給人感覺(jué)是動(dòng)態(tài)的竣稽,而不是直接生硬的瞬間出現(xiàn)多張圖片的發(fā)送囱怕。
由于耗時(shí)計(jì)算是在子線(xiàn)程當(dāng)中槽唾,當(dāng)子線(xiàn)程中完成操作后,我們要回到主線(xiàn)程中去執(zhí)行下一步操作光涂,這里有兩種回到主線(xiàn)程的方式:
1??參數(shù)的意義:1、執(zhí)行在主線(xiàn)程的方法 2拧烦、傳遞的參數(shù) 3忘闻、是否等待完成后操作
[self performSelectorOnMainThread:@selector(mainAction:) withObject:@(sum) waitUntilDone:YES];
-(void)mainAction:(NSNumber *)sum{
NSLog(@"計(jì)算的結(jié)果%d",[sum intValue]);
NSLog(@"當(dāng)前線(xiàn)程是否為主線(xiàn)程:%d",[NSThread isMainThread]);
}
打印結(jié)果:
2??
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"===計(jì)算的結(jié)果%d",sum);
NSLog(@"===當(dāng)前線(xiàn)程是否為主線(xiàn)程:%d",[NSThread isMainThread]);
});
靜態(tài)方法直接開(kāi)辟子線(xiàn)程:
[NSThread detachNewThreadSelector:@selector(calculateAction) toTarget:self withObject:nil];
2、NSObject
[self performSelectorInBackground:@selector(calculateAction) withObject:nil];
3恋博、NSOperationQuene
NSOperationQuene:此種多線(xiàn)程方式和NSOperation的兩個(gè)子類(lèi)來(lái)結(jié)合使用實(shí)現(xiàn)多線(xiàn)程方式
// 3.1
NSInvocationOperation *invocation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(calculateAction) object:nil];
// 3.2
NSBlockOperation *block = [NSBlockOperation blockOperationWithBlock:^{
[self test];
}];
// 創(chuàng)建管理隊(duì)列的兩個(gè)任務(wù)
NSOperationQueue *queue = [NSOperationQueue new];
// 設(shè)置最大并發(fā)數(shù)(同時(shí)執(zhí)行的任務(wù)個(gè)數(shù))
// 若最大并發(fā)數(shù)設(shè)置為1.那么任務(wù)按照串行方式執(zhí)行(1就是跟串聯(lián)一樣)
[queue setMaxConcurrentOperationCount:2];
// 將任務(wù)添加到隊(duì)列
[queue addOperation:invocation];
[queue addOperation:block];
一個(gè)檢測(cè)先后順序的test方法
-(void)test{
NSLog(@"測(cè)試的時(shí)間齐佳。。债沮。炼吴。");
}
那么,最后輸出的結(jié)果是:
可以得出的結(jié)論是:隊(duì)列中先加入誰(shuí)就先執(zhí)行誰(shuí)疫衩,但是不代表先執(zhí)行的方法就先結(jié)束硅蹦。
4、GCD
兩種隊(duì)列方式:并行隊(duì)列闷煤,串行隊(duì)列
并行隊(duì)列:所有任務(wù)并發(fā)執(zhí)行童芹,不分先后
串行隊(duì)列:所有任務(wù)一次執(zhí)行,排隊(duì)完成
GCD中鲤拿,有三種隊(duì)列可以使用
主隊(duì)列:系統(tǒng)提供的單例假褪,屬于串行隊(duì)列
全局隊(duì)列:系統(tǒng)提供的單例,屬于并行隊(duì)列
自定義隊(duì)列:開(kāi)發(fā)人員可以自定義選擇使用串行或并行
主隊(duì)列
輸出結(jié)果是:為順序執(zhí)行的串行隊(duì)列
全局隊(duì)列:并行隊(duì)列(也遵循FIFO近顷,先進(jìn)先出原則)---會(huì)開(kāi)辟子線(xiàn)程生音,但是其管理的任務(wù)不一定只在子線(xiàn)程執(zhí)行,也會(huì)添加到主線(xiàn)程執(zhí)行
// 1窒升、隊(duì)列優(yōu)先級(jí)
// 2缀遍、空余參數(shù),以后添加作用
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 必須先執(zhí)行的代碼(第一個(gè)加入隊(duì)列時(shí)饱须,才會(huì)優(yōu)先執(zhí)行此任務(wù))
dispatch_barrier_sync(globalQueue, ^{
NSLog(@"優(yōu)先執(zhí)行的代碼");
});
dispatch_async(globalQueue, ^{
NSLog(@"第一個(gè)任務(wù):%d",[NSThread isMainThread]);
});
dispatch_async(globalQueue, ^{
NSLog(@"第二個(gè)任務(wù):%d",[NSThread isMainThread]);
});
dispatch_async(globalQueue, ^{
NSLog(@"第三個(gè)任務(wù):%d",[NSThread isMainThread]);
});
// 延時(shí)啟動(dòng)任務(wù)
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), globalQueue, ^{
NSLog(@"出來(lái)吧瑟由,神龍!");
});
// 反復(fù)執(zhí)行n次的任務(wù)
dispatch_apply(3, globalQueue, ^(size_t time) {
NSLog(@"第%zu次",time);
});
// 添加函數(shù)
//? 參數(shù):1冤寿、要把任務(wù)添加到的隊(duì)列 2歹苦、函數(shù)的參數(shù) 3、函數(shù)
dispatch_async_f(globalQueue, "I love my iOS teacher", function);
// 函數(shù)
void function(void * string);
void function(void * string){
NSLog(@"%s",string);
}
輸出結(jié)果:
由此可以看出督怜,第一到第三個(gè)任務(wù)并不是順序執(zhí)行的殴瘦。為并行執(zhí)行。
自定義隊(duì)列
串行
當(dāng)全部為sync時(shí)号杠,線(xiàn)程順序執(zhí)行蚪腋,優(yōu)先在當(dāng)前線(xiàn)程中執(zhí)行丰歌,打印結(jié)果是:
當(dāng)為async時(shí),線(xiàn)程并行執(zhí)行
并行隊(duì)列屉凯,當(dāng)前線(xiàn)程為并行執(zhí)行立帖,且在用async,即異步的時(shí)候悠砚,是在子線(xiàn)程中執(zhí)行
串行但異步執(zhí)行
并行但異步執(zhí)行
分組:異步執(zhí)行
對(duì)線(xiàn)程的一些小總結(jié)晓勇,很簡(jiǎn)單,后續(xù)進(jìn)行深入補(bǔ)充灌旧。