在我們做的項(xiàng)目中盔沫,這些線程間的通訊多用于圖片的下載钠四,而這些常常SDWebImage或者YYWebImage 都會(huì)給我們做好踱阿,所以我寫(xiě)的并無(wú)卵用透罢,
- 下面來(lái)總結(jié)一下線程間通信的幾種方法 :
- NSThread
- GCD
- NSOperation
- NSthread:
優(yōu)點(diǎn):比其他兩種輕量級(jí)。
缺點(diǎn):需要自己管理線程的生命周期,線程同步廓啊。 線程同步對(duì)數(shù)據(jù)的加鎖會(huì)有一定的開(kāi)銷(xiāo)欢搜。
-
Operation、GCD:
優(yōu)點(diǎn):不需要關(guān)心線程管理谴轮,數(shù)據(jù)同步的事情炒瘟。
兩者區(qū)別:NSOperationQueue可以方便的管理并發(fā)、 NSOperation之間的優(yōu)先級(jí)第步。GCD主要與block結(jié)合使用疮装。代碼簡(jiǎn)潔高效
- 性能:GCD更接近底層,而NSOperationQueue則更高級(jí)抽象雌续,所以GCD在追求性能的底層操作來(lái)說(shuō)斩个,是速度最快的。這取決于使用Instruments進(jìn)行代碼性能分析驯杜,如有必要的話
- 從異步操作之間的事務(wù)性,順序行做个,依賴關(guān)系鸽心。GCD需要自己寫(xiě)更多的代碼來(lái)實(shí)現(xiàn),而NSOperationQueue已經(jīng)內(nèi)建了這些支持
- 如果異步操作的過(guò)程需要更多的被交互和UI呈現(xiàn)出來(lái)居暖,NSOperationQueue會(huì)是一個(gè)更好的選擇顽频。底層代碼中,任務(wù)之間不太互相依賴太闺,而需要更高的并發(fā)能力糯景,GCD則更有優(yōu)勢(shì)
<h3>☆分別用這三個(gè)方法創(chuàng)建一個(gè)下載圖片的案例
NSThread
- (void)thread{
//1.去網(wǎng)絡(luò)上加載數(shù)據(jù)
NSString *imageURLString = @"http://imgsrc.baidu.com/forum/w%3D580/sign=13eeace7d058ccbf1bbcb53229d9bcd4/9245d688d43f879404f24d7bd31b0ef41bd53a51.jpg";
[self performSelectorInBackground:@selector(loadImage:) withObject:imageURLString];//
}
- (void)loadImage:(NSString *)imageURLString{
NSLog(@"loadImage--- %@",[NSThread currentThread]);
//1.拿著imageURLString去網(wǎng)絡(luò)上下載
NSURL *url = [NSURL URLWithString:imageURLString];
//2.去網(wǎng)絡(luò)上加載圖片
NSData *imageData = [NSData dataWithContentsOfURL:url];
//3.將我們從網(wǎng)絡(luò)上獲取到的圖片的二進(jìn)制,轉(zhuǎn)成UIImage
UIImage *image = [UIImage imageWithData:imageData];
//4.回到主線程,并且將image傳給主線程,讓主線程去更新UI
[self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];//YES同步,NO 異步
NSLog(@"---子線程over---");
}
- (void)updateUI:(UIImage *)image{
NSLog(@"updateUI---%@",[NSThread currentThread]);
self.imageView.image = image;
}
GCD
- (void)gcd{
NSString *imageURLString = @"http://imgsrc.baidu.com/forum/w%3D580/sign=13eeace7d058ccbf1bbcb53229d9bcd4/9245d688d43f879404f24d7bd31b0ef41bd53a51.jpg";
//1.去子線程,下載圖片,這是一個(gè)耗時(shí)間的操作
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"gcd---loadImage===%@",[NSThread currentThread]);
//1.1.拿著imageURLString去網(wǎng)絡(luò)上下載
NSURL *url = [NSURL URLWithString:imageURLString];
//1.2.去網(wǎng)絡(luò)上加載圖片
NSData *imageData = [NSData dataWithContentsOfURL:url];
//1.3.將我們從網(wǎng)絡(luò)上獲取到的圖片的二進(jìn)制,轉(zhuǎn)成UIImage
UIImage *image = [UIImage imageWithData:imageData];
//2.回到主線程更新UI
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"updateUI---%@",[NSThread currentThread]);
weakSelf.imageView.image = image;
});
});
//2.回到主線程更新UI
}
☆NSOperation (SDWebImage或者YYWebImage)都是這樣實(shí)現(xiàn)的
NSOperation 有兩個(gè)子類(lèi)(不好使),但通常是用第三種方法實(shí)現(xiàn)
1> NSInvocationOperation
2> NSBlockOperation
3> 自定義子類(lèi)繼承NSOperation省骂,實(shí)現(xiàn)內(nèi)部相應(yīng)的方法
- 創(chuàng)建一個(gè)繼承 NSOperation 的類(lèi)
- 創(chuàng)建一個(gè)下載任務(wù)器蟀淮,創(chuàng)建一個(gè)隊(duì)列,任務(wù)添加隊(duì)列钞澳,這時(shí)會(huì)執(zhí)行自定義operation類(lèi)里的 main 方法
- 在任務(wù)器中異步下載圖片
- 返回主線程跟新UI
- (void)operation{
//1.自定義一個(gè)下載的任務(wù)
__weak typeof(self) weakSelf = self;
DownLoadOperation *downLoadOp = [[DownLoadOperation alloc] init];
downLoadOp.imageURLString = @"http://e.hiphotos.bdimg.com/album/pic/item/9345d688d43f8794f0ab07ddd01b0ef41ad53ae8.jpg";
downLoadOp.finshedBlock = ^(UIImage *image){
//NSLog(@"%@---%@",image,[NSThread currentThread]);
//2.回到主線程更新UI
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
//在主線程
weakSelf.imageView.image = image;
}];
};
//2.隊(duì)列
NSOperationQueue *concurrentQueue = [[NSOperationQueue alloc] init];
//3.將我們的任務(wù),添加到隊(duì)列中,然后隊(duì)列就會(huì)調(diào)度downLoadOp,去調(diào)用downLoadOp它的main
[concurrentQueue addOperation:downLoadOp];
}
下載容器
#import <UIKit/UIKit.h>
//typedef int MyInt;
//一般建議首字母大寫(xiě)
typedef void(^FinishedBlock)(UIImage *image);
@interface DownLoadOperation : NSOperation
// 圖片url地址
@property (nonatomic , copy) NSString *imageURLString;
// 回調(diào)的block
@property (nonatomic , copy) FinishedBlock finshedBlock;
@end
#import "DownLoadOperation.h"
@implementation DownLoadOperation
- (void)main{
//因?yàn)槲覀兊拿恳粋€(gè)線程在使用過(guò)程中,都會(huì)產(chǎn)生對(duì)象,當(dāng)我們線程結(jié)束的時(shí)候,需要對(duì)我們?cè)谠摼€程中使用過(guò)的對(duì)象,做release
@autoreleasepool {
NSLog(@"---main----%@",[NSThread currentThread]);
//1.1.拿著imageURLString去網(wǎng)絡(luò)上下載
NSURL *url = [NSURL URLWithString:self.imageURLString];
//1.2.去網(wǎng)絡(luò)上加載圖片
NSData *imageData = [NSData dataWithContentsOfURL:url];
//1.3.將我們從網(wǎng)絡(luò)上獲取到的圖片的二進(jìn)制,轉(zhuǎn)成UIImage
UIImage *image = [UIImage imageWithData:imageData];
//2.這個(gè)時(shí)候通過(guò)block將我們的image,傳給控制器
if (self.finshedBlock) {
self.finshedBlock(image);
}
}
}
@end