一.基本概念
計算機(jī)操作系統(tǒng)都有的基本概念僧界,以下概念簡單方式來描述侨嘀。
進(jìn)程: 一個具有一定獨(dú)立功能的程序關(guān)于某個數(shù)據(jù)集合的一次運(yùn)行活動∥娼螅可以理解成一個運(yùn)行中的應(yīng)用程序咬腕。
線程: 程序執(zhí)行流的最小單元,線程是進(jìn)程中的一個實體葬荷。
同步: 只能在當(dāng)前線程按先后順序依次執(zhí)行涨共,不開啟新線程纽帖。
異步: 可以在當(dāng)前線程開啟多個新線程執(zhí)行,可不按順序執(zhí)行煞赢。
隊列: 裝載線程任務(wù)的隊形結(jié)構(gòu)抛计。
并發(fā): 線程執(zhí)行可以同時一起進(jìn)行執(zhí)行。
串行: 線程執(zhí)行只能依次逐一先后有序的執(zhí)行照筑。
注意:
一個進(jìn)程可有多個線程吹截。
一個進(jìn)程可有多個隊列。
隊列可分并發(fā)隊列和串行隊列凝危。
二.iOS多線程對比
1. NSThread
每個NSThread對象對應(yīng)一個線程波俄,真正最原始的線程。
1)優(yōu)點:NSThread 輕量級最低蛾默,相對簡單懦铺。
2)缺點:手動管理所有的線程活動,如生命周期支鸡、線程同步冬念、睡眠等。
2. NSOperation
自帶線程管理的抽象類牧挣。
1)優(yōu)點:自帶線程周期管理急前,操作上可更注重自己邏輯。
2)缺點:面向?qū)ο蟮某橄箢惼俟梗荒軐崿F(xiàn)它或者使用它定義好的兩個子類:NSInvocationOperation 和 NSBlockOperation裆针。
3. GCD
Grand Central Dispatch (GCD)是Apple開發(fā)的一個多核編程的解決方法。
1)優(yōu)點:最高效寺晌,避開并發(fā)陷阱世吨。
2)缺點:基于C實現(xiàn)。
5. 選擇小結(jié)
1)簡單而安全的選擇NSOperation實現(xiàn)多線程即可呻征。
2)處理大量并發(fā)數(shù)據(jù)耘婚,又追求性能效率的選擇GCD。
3)NSThread本人選擇基本上是在做些小測試上使用陆赋,當(dāng)然也可以基于此造個輪子边篮。
三.場景選擇
圖片異步加載。這種常見的場景是最常見也是必不可少的奏甫。異步加載圖片有分成兩種來說明一下。
第一種凌受,在UI主線程開啟新線程按順序加載圖片阵子,加載完成刷新UI。
第二種胜蛉,依然是在主線程開啟新線程挠进,順序不定地加載圖片色乾,加載完成個字刷新UI。
創(chuàng)作工具上的異步领突。 這個跟上邊任務(wù)調(diào)度道理暖璧,只是為了豐富描述,有助于“舉一反三”效果君旦。如下描述的是app創(chuàng)作小說澎办。
場景一,app本地創(chuàng)作10個章節(jié)內(nèi)容未成同步服務(wù)器金砍,同時發(fā)表這10個章節(jié)產(chǎn)生的一系列動作局蚀,其中上傳內(nèi)容,獲取分配章節(jié)Id恕稠,如何后臺沒有做處理最好方式做異步按順序執(zhí)行琅绅。
場景二,app本地創(chuàng)作列表中有3本小說為發(fā)表鹅巍,同時發(fā)表創(chuàng)作列表中的3本小說千扶,自然考慮并行隊列執(zhí)行發(fā)表。
四.使用方法
第三標(biāo)題場景選擇內(nèi)容實現(xiàn)先留下一個懸念骆捧。具體實現(xiàn)還是先熟知一下各自的API先澎羞。
1. NSThread
1.1)三種實現(xiàn)開啟線程方式:
①.動態(tài)實例化
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(loadImageSource:) object:imgUrl];
thread.threadPriority = 1;// 設(shè)置線程的優(yōu)先級(0.0 - 1.0,1.0最高級)
[thread start];
②.靜態(tài)實例化
[NSThread detachNewThreadSelector:@selector(loadImageSource:) toTarget:self withObject:imgUrl];
③.隱式實例化
[self performSelectorInBackground:@selector(loadImageSource:) withObject:imgUrl];
有了以上的知識點凑懂,可以試探了一下編寫場景選擇中的“圖片加載”的基本功能了煤痕。
1.2)使用這三種方式編寫代碼
//動態(tài)創(chuàng)建線程
-(void)dynamicCreateThread{
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(loadImageSource:) object:imgUrl];
thread.threadPriority = 1;// 設(shè)置線程的優(yōu)先級(0.0 - 1.0,1.0最高級)
[thread start];
}
//靜態(tài)創(chuàng)建線程
-(void)staticCreateThread{
[NSThread detachNewThreadSelector:@selector(loadImageSource:) toTarget:self withObject:imgUrl];
}
//隱式創(chuàng)建線程
-(void)implicitCreateThread{
[self performSelectorInBackground:@selector(loadImageSource:) withObject:imgUrl];
}
-(void)loadImageSource:(NSString *)url{
NSData *imgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
UIImage *image = [UIImage imageWithData:imgData];
if (imgData!=nil) {
[self performSelectorOnMainThread:@selector(refreshImageView:) withObject:image waitUntilDone:YES];
}else{
NSLog(@"there no image data");
}
}
-(void)refreshImageView:(UIImage *)image{
[self.imageView setImage:image];
}