在我們做的項目中,這些線程間的通訊多用于圖片的下載,而這些常常SDWebImage或者YYWebImage 都會給我們做好,所以我寫的并無卵用,
- 下面來總結(jié)一下線程間通信的幾種方法 :
- NSThread
- GCD
- NSOperation
- NSthread:
優(yōu)點:比其他兩種輕量級。
缺點:需要自己管理線程的生命周期,線程同步。 線程同步對數(shù)據(jù)的加鎖會有一定的開銷。
-
Operation、GCD:
優(yōu)點:不需要關(guān)心線程管理,數(shù)據(jù)同步的事情。
兩者區(qū)別:NSOperationQueue可以方便的管理并發(fā)、 NSOperation之間的優(yōu)先級。GCD主要與block結(jié)合使用。代碼簡潔高效
- 性能:GCD更接近底層,而NSOperationQueue則更高級抽象,所以GCD在追求性能的底層操作來說,是速度最快的。這取決于使用Instruments進(jìn)行代碼性能分析,如有必要的話
- 從異步操作之間的事務(wù)性,順序行,依賴關(guān)系。GCD需要自己寫更多的代碼來實現(xiàn),而NSOperationQueue已經(jīng)內(nèi)建了這些支持
- 如果異步操作的過程需要更多的被交互和UI呈現(xiàn)出來,NSOperationQueue會是一個更好的選擇。底層代碼中,任務(wù)之間不太互相依賴,而需要更高的并發(fā)能力,GCD則更有優(yōu)勢
<h3>☆分別用這三個方法創(chuàng)建一個下載圖片的案例
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.去子線程,下載圖片,這是一個耗時間的操作
__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)都是這樣實現(xiàn)的
NSOperation 有兩個子類(不好使),但通常是用第三種方法實現(xiàn)
1> NSInvocationOperation
2> NSBlockOperation
3> 自定義子類繼承NSOperation,實現(xiàn)內(nèi)部相應(yīng)的方法
- 創(chuàng)建一個繼承 NSOperation 的類
- 創(chuàng)建一個下載任務(wù)器,創(chuàng)建一個隊列,任務(wù)添加隊列,這時會執(zhí)行自定義operation類里的 main 方法
- 在任務(wù)器中異步下載圖片
- 返回主線程跟新UI
- (void)operation{
//1.自定義一個下載的任務(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.隊列
NSOperationQueue *concurrentQueue = [[NSOperationQueue alloc] init];
//3.將我們的任務(wù),添加到隊列中,然后隊列就會調(diào)度downLoadOp,去調(diào)用downLoadOp它的main
[concurrentQueue addOperation:downLoadOp];
}
下載容器
#import <UIKit/UIKit.h>
//typedef int MyInt;
//一般建議首字母大寫
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{
//因為我們的每一個線程在使用過程中,都會產(chǎn)生對象,當(dāng)我們線程結(jié)束的時候,需要對我們在該線程中使用過的對象,做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.這個時候通過block將我們的image,傳給控制器
if (self.finshedBlock) {
self.finshedBlock(image);
}
}
}
@end