一库北、簡(jiǎn)介
1.NSOperation的作用
配合使用NSOperation和NSOperationQueue也能實(shí)現(xiàn)多線程編程
2.NSOperation和NSOperationQueue實(shí)現(xiàn)多線程的具體步驟
先將需要執(zhí)行的操作封裝到一個(gè)NSOperation對(duì)象中
然后將NSOperation對(duì)象添加到NSOperationQueue中
系統(tǒng)會(huì)自動(dòng)將NSOperationQueue中的NSOperation取出來(lái)
將取出的NSOperation封裝的操作放到一條新線程中執(zhí)行
2.NSOperation的子類
NSOperation是個(gè)抽象類,并不具備封裝操作的能力,必須使用它的子類.
使用NSOperation子類的方式有3種
NSInvocationOperation
NSBlockOperation
自定義子類繼承NSOperation邓深,實(shí)現(xiàn)內(nèi)部相應(yīng)的方法
二狸页、NSInvocationOperation
默認(rèn)情況下哈踱,調(diào)用了start方法后并不會(huì)開(kāi)一條新線程去執(zhí)行操作,而是在當(dāng)前線程同步執(zhí)行操作
只有將NSOperation放到一個(gè)NSOperationQueue中玉转,才會(huì)異步執(zhí)行操作
- (void)invocationOperation
{
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];
[op start];
}
- (void)run
{
NSLog(@"------%@", [NSThread currentThread]);
}
三、NSBlockOperation
只要NSBlockOperation封裝的操作數(shù) >1殴蹄,就會(huì)異步執(zhí)行操作
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
// 在主線程
NSLog(@"下載1------%@", [NSThread currentThread]);
}];
// 添加額外的任務(wù)(在子線程執(zhí)行)
[op addExecutionBlock:^{
NSLog(@"下載2------%@", [NSThread currentThread]);
}];
[op addExecutionBlock:^{
NSLog(@"下載3------%@", [NSThread currentThread]);
}];
[op addExecutionBlock:^{
NSLog(@"下載4------%@", [NSThread currentThread]);
}];
[op start];
四究抓、NSOperationQueue
1.NSOperationQueue的作用
如果將NSOperation添加到NSOperationQueue(操作隊(duì)列)中,系統(tǒng)會(huì)自動(dòng)異步執(zhí)行NSOperation中的操作
2.添加操作到NSOperationQueue中
(1)-(void)addOperation:(NSOperation*)op;
// 創(chuàng)建隊(duì)列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 創(chuàng)建操作(任務(wù))
// 創(chuàng)建NSInvocationOperation
NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download1) object:nil];
NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download2) object:nil];
// 創(chuàng)建NSBlockOperation
NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"download3 --- %@", [NSThread currentThread]);
}];
[op3 addExecutionBlock:^{
NSLog(@"download4 --- %@", [NSThread currentThread]);
}];
[op3 addExecutionBlock:^{
NSLog(@"download5 --- %@", [NSThread currentThread]);
}];
NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"download6 --- %@", [NSThread currentThread]);
}];
// 創(chuàng)建XMGOperation
XMGOperation *op5 = [[XMGOperation alloc] init];
// 添加任務(wù)到隊(duì)列中
[queue addOperation:op1]; // [op1 start]
[queue addOperation:op2]; // [op2 start]
[queue addOperation:op3]; // [op3 start]
[queue addOperation:op4]; // [op4 start]
[queue addOperation:op5]; // [op5 start]
(2)-(void)addOperationWithBlock:(void(^)(void))block;
// 創(chuàng)建隊(duì)列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 創(chuàng)建操作
// NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
// NSLog(@"download1 --- %@", [NSThread currentThread]);
// }];
// 添加操作到隊(duì)列中
// [queue addOperation:op1];
[queue addOperationWithBlock:^{
NSLog(@"download1 --- %@", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"download2 --- %@", [NSThread currentThread]);
}];
3.最大并發(fā)數(shù)
// 創(chuàng)建隊(duì)列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 設(shè)置最大并發(fā)操作數(shù)
// queue.maxConcurrentOperationCount = 2;
queue.maxConcurrentOperationCount = 1; // 就變成了串行隊(duì)列
// 添加操作
[queue addOperationWithBlock:^{
NSLog(@"download1 --- %@", [NSThread currentThread]);
[NSThread sleepForTimeInterval:0.01];
}];
[queue addOperationWithBlock:^{
NSLog(@"download2 --- %@", [NSThread currentThread]);
[NSThread sleepForTimeInterval:0.01];
}];
[queue addOperationWithBlock:^{
NSLog(@"download3 --- %@", [NSThread currentThread]);
[NSThread sleepForTimeInterval:0.01];
}];
4.隊(duì)列的取消袭灯、暫停和恢復(fù)
// 創(chuàng)建隊(duì)列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
self.queue = queue;
// if (self.queue.isSuspended) {
// // 恢復(fù)隊(duì)列刺下,繼續(xù)執(zhí)行
// self.queue.suspended = NO;
// } else {
// // 暫停(掛起)隊(duì)列,暫停執(zhí)行
// self.queue.suspended = YES;
// }
[self.queue cancelAllOperations];
5.NSOperation之間可以設(shè)置依賴來(lái)保證執(zhí)行順序
比如一定要讓操作A執(zhí)行完后稽荧,才能執(zhí)行操作B橘茉,可以這么寫(xiě)
[operationB addDependency:operationA];
注意:不能相互依賴
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"download1----%@", [NSThread currentThread]);
}];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"download2----%@", [NSThread currentThread]);
}];
NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"download3----%@", [NSThread currentThread]);
}];
NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
for (NSInteger i = 0; i<10; i++) {
NSLog(@"download4----%@", [NSThread currentThread]);
}
}];
NSBlockOperation *op5 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"download5----%@", [NSThread currentThread]);
}];
op5.completionBlock = ^{
NSLog(@"op5執(zhí)行完畢---%@", [NSThread currentThread]);
};
// 設(shè)置依賴
[op3 addDependency:op1];
[op3 addDependency:op2];
[op3 addDependency:op4];
[queue addOperation:op1];
[queue addOperation:op2];
[queue addOperation:op3];
[queue addOperation:op4];
[queue addOperation:op5];
五、線程間的通信
[[[NSOperationQueue alloc] init] addOperationWithBlock:^{
// 圖片的網(wǎng)絡(luò)路徑
NSURL *url = [NSURL URLWithString:@"http://img.pconline.com.cn/images/photoblog/9/9/8/1/9981681/200910/11/1255259355826.jpg"];
// 加載圖片
NSData *data = [NSData dataWithContentsOfURL:url];
// 生成圖片
UIImage *image = [UIImage imageWithData:data];
// 回到主線程
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
self.imageView.image = image;
}];
}];
六姨丈、多線程下載圖片
#import "ViewController.h"
#import "XMGApp.h"
@interface ViewController ()
/** 所有數(shù)據(jù) */
@property (nonatomic, strong) NSArray *apps;
/** 內(nèi)存緩存的圖片 */
@property (nonatomic, strong) NSMutableDictionary *images;
/** 隊(duì)列對(duì)象 */
@property (nonatomic, strong) NSOperationQueue *queue;
@end
@implementation ViewController
- (NSOperationQueue *)queue
{
if (!_queue) {
_queue = [[NSOperationQueue alloc] init];
_queue.maxConcurrentOperationCount = 3;
}
return _queue;
}
- (NSMutableDictionary *)images
{
if (!_images) {
_images = [NSMutableDictionary dictionary];
}
return _images;
}
- (NSArray *)apps
{
if (!_apps) {
NSArray *dictArray = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"apps.plist" ofType:nil]];
NSMutableArray *appArray = [NSMutableArray array];
for (NSDictionary *dict in dictArray) {
[appArray addObject:[XMGApp appWithDict:dict]];
}
_apps = appArray;
}
return _apps;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
#pragma mark - 數(shù)據(jù)源方法
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.apps.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ID = @"app";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
XMGApp *app = self.apps[indexPath.row];
cell.textLabel.text = app.name;
cell.detailTextLabel.text = app.download;
// 先從內(nèi)存緩存中取出圖片
UIImage *image = self.images[app.icon];
if (image) { // 內(nèi)存中有圖片
cell.imageView.image = image;
} else { // 內(nèi)存中沒(méi)有圖片
// 獲得Library/Caches文件夾
NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
// 獲得文件名
NSString *filename = [app.icon lastPathComponent];
// 計(jì)算出文件的全路徑
NSString *file = [cachesPath stringByAppendingPathComponent:filename];
// 加載沙盒的文件數(shù)據(jù)
NSData *data = [NSData dataWithContentsOfFile:file];
if (data) { // 直接利用沙盒中圖片
UIImage *image = [UIImage imageWithData:data];
cell.imageView.image = image;
// 存到字典中
self.images[app.icon] = image;
} else { // 下載圖片
[self.queue addOperationWithBlock:^{
// 下載圖片
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:app.icon]];
UIImage *image = [UIImage imageWithData:data];
[NSThread sleepForTimeInterval:1.0];
// 回到主線程顯示圖片
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
cell.imageView.image = image;
}];
// 存到字典中
self.images[app.icon] = image;
// 將圖片文件數(shù)據(jù)寫(xiě)入沙盒中
[data writeToFile:file atomically:YES];
}];
}
}
return cell;
}
@end