- (void)singleBlockOperation{ NSLog(@"thread == %@ 1",[NSThread currentThread]); NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^(){ NSLog(@"thread == %@ doing a operation",[NSThread currentThread]); }]; // 开始执行任务 NSLog(@"thread == %@ 2",[NSThread currentThread]); [operation start]; NSLog(@"thread == %@ after operation",[NSThread currentThread]); }
打印内容html
2016-11-12 10:17:13.001 MutipleThreadPractice[77168:3862880] thread == <NSThread: 0x7f9451704800>{number = 1, name = main} 1 2016-11-12 10:17:13.002 MutipleThreadPractice[77168:3862880] thread == <NSThread: 0x7f9451704800>{number = 1, name = main} 2 2016-11-12 10:17:13.002 MutipleThreadPractice[77168:3862880] thread == <NSThread: 0x7f9451704800>{number = 1, name = main} doing a operation 2016-11-12 10:17:13.002 MutipleThreadPractice[77168:3862880] thread == <NSThread: 0x7f9451704800>{number = 1, name = main} after operation
- (void)multipleBlockOperation{ NSLog(@"thread== %@ start", [NSThread currentThread]); NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^(){ NSLog(@"thread== %@ 1", [NSThread currentThread]); }]; [operation addExecutionBlock:^() { NSLog(@"thread== %@ 2", [NSThread currentThread]); }]; [operation addExecutionBlock:^() { NSLog(@"thread== %@ 3", [NSThread currentThread]); }]; [operation addExecutionBlock:^() { NSLog(@"thread== %@ 4", [NSThread currentThread]); }]; NSLog(@"thread== %@ 5", [NSThread currentThread]); // 开始执行任务 [operation start]; NSLog(@"thread== %@ 6", [NSThread currentThread]); }
打印纪录ios
2016-11-12 10:23:59.998 MutipleThreadPractice[77537:3867741] thread== <NSThread: 0x7fb4f16040c0>{number = 1, name = main} start 2016-11-12 10:23:59.998 MutipleThreadPractice[77537:3867741] thread== <NSThread: 0x7fb4f16040c0>{number = 1, name = main} 5 2016-11-12 10:23:59.998 MutipleThreadPractice[77537:3867741] thread== <NSThread: 0x7fb4f16040c0>{number = 1, name = main} 1 2016-11-12 10:23:59.998 MutipleThreadPractice[77537:3867741] thread== <NSThread: 0x7fb4f16040c0>{number = 1, name = main} 2 2016-11-12 10:23:59.999 MutipleThreadPractice[77537:3867741] thread== <NSThread: 0x7fb4f16040c0>{number = 1, name = main} 4 2016-11-12 10:23:59.999 MutipleThreadPractice[77537:3869224] thread== <NSThread: 0x7fb4f1719040>{number = 4, name = (null)} 3 2016-11-12 10:24:00.001 MutipleThreadPractice[77537:3867741] thread== <NSThread: 0x7fb4f16040c0>{number = 1, name = main} 6
[operation cancel];
MyDownloadOperation *downloadOp = [[MyDownloadOperation alloc] init]; // MyDownloadOperation is a subclass of NSOperation
MyFilterOperation *filterOp = [[MyFilterOperation alloc] init]; // MyFilterOperation is a subclass of NSOperation
[filterOp addDependency:downloadOp];
要删除依赖性:
[filterOp removeDependency:downloadOp];编程
operation.completionBlock = ^() { NSLog(@"执行完毕"); };
NSOperationQueue *myQueue = [[NSOperationQueue alloc] init];
myQueue.name = @"Download Queue";缓存
你能够设定NSOperationQueue能够并发运行的最大操做数。NSOperationQueue会选择去运行任何数量的并发操做,可是不会超过最大值。多线程
myQueue.MaxConcurrentOperationCount = 3;并发
若是你改变了主意,想将MaxConcurrentOperationCount设置回默认值,你能够执行下列操做:app
myQueue.MaxConcurrentOperationCount = NSOperationQueueDefaultMaxConcurrentOperationCount; 异步
任什么时候候你能够询问一个队列哪一个操做在里面,而且总共有多少个操做在里面。记住只有那些等待被执行的操做,还有那些正在运行的操做,会被保留在队列中。操做一完成,就会退出队列。
NSArray *active_and_pending_operations = myQueue.operations;
NSInteger count_of_operations = myQueue.operationCount; async
暂停队列:你能够经过设定setSuspended:YES来暂停一个队列。这样会暂停全部在队列中的操做 — 你不能单独的暂停操做。要从新开始队列,只要简单的setSuspended:NO。
// Suspend a queue
[myQueue setSuspended:YES];
.
.
.
// Resume a queue
[myQueue setSuspended: NO];
取消操做:要取消一个队列中的全部操做,你只要简单的调用“cancelAllOperations”方法便可。还记得以前提醒过常常检查NSOperation中的isCancelled属性吗?atom
UIImage *myImage = nil; // Create a weak reference __weak UIImage *myImage_weak = myImage; // Add an operation as a block to a queue [myQueue addOperationWithBlock: ^ { // a block of operation NSURL *aURL = [NSURL URLWithString:@"http://www.somewhere.com/image.png"]; NSError *error = nil; NSData *data = [NSData dataWithContentsOfURL:aURL options:nil error:&error]; If (!error) [myImage_weak imageWithData:data]; // Get hold of main queue (main thread) [[NSOperationQueue mainQueue] addOperationWithBlock: ^ { myImageView.image = myImage_weak; // updating UI }]; }];
自定义了一个NSOperation的子类,而后重写main方法。并定义了一个代理方法,用来处理Operation执行完毕后的操做。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <array> <dict> <key>icon</key> <string>http://zbimg.25pp.com/images/artwork/102/951610982_54x54.jpg</string> <key>name</key> <string>菜鸟裹裹</string> <key>download</key> <string></string> </dict> <dict> <key>icon</key> <string>http://zbimg.25pp.com/images/artwork/92/855031900_54x54.jpg</string> <key>name</key> <string>十六番</string> <key>download</key> <string></string> </dict> <dict> <key>icon</key> <string>http://zbimg.25pp.com/images/artwork/246/950137846_54x54.jpg</string> <key>name</key> <string>暴风魔镜Pro</string> <key>download</key> <string></string> </dict> <dict> <key>icon</key> <string>http://zbimg.25pp.com/images/artwork/189/1044569021_54x54.jpg</string> <key>name</key> <string>斗图神器</string> <key>download</key> <string></string> </dict> <dict> <key>icon</key> <string>http://zbimg.25pp.com/images/artwork/80/1048881232_54x54.jpg</string> <key>name</key> <string>糖果工厂</string> <key>download</key> <string></string> </dict> <dict> <key>icon</key> <string>http://zbimg.25pp.com/images/artwork/110/656554606_54x54.jpg</string> <key>name</key> <string>念力移物</string> <key>download</key> <string></string> </dict> <dict> <key>icon</key> <string>http://zbimg.25pp.com/images/artwork/218/904209370_54x54.jpg</string> <key>name</key> <string>B612</string> <key>download</key> <string></string> </dict> </array> </plist>
#import <Foundation/Foundation.h> @interface YYappModel : NSObject /** *应用名称 */ @property(nonatomic,copy)NSString *name; /** * 应用图片 */ @property(nonatomic,copy)NSString *icon; /** * 应用的下载量 */ @property(nonatomic,copy)NSString *download; +(instancetype)appModelWithDict:(NSDictionary *)dict; -(instancetype)initWithDict:(NSDictionary *)dict; @end
#import "YYappModel.h" @implementation YYappModel -(instancetype)initWithDict:(NSDictionary *)dict { if (self=[super init]) { [self setValuesForKeysWithDictionary:dict]; } return self; } //工厂方法 +(instancetype)appModelWithDict:(NSDictionary *)dict { return [[self alloc]initWithDict:dict]; } @end
#import <Foundation/Foundation.h> #pragma mark -设置代理和代理方法 @class YYdownLoadOperation; @protocol YYdownLoadOperationDelegate <NSObject> - (void)downLoadOperation:(YYdownLoadOperation *)operation didFishedDownLoad:(UIImage *)image; @end @interface YYdownLoadOperation : NSOperation @property(nonatomic, copy) NSString *url; @property(nonatomic, strong) NSIndexPath *indexPath; @property(nonatomic, strong) id<YYdownLoadOperationDelegate> delegate; @end
#import "YYdownLoadOperation.h" @implementation YYdownLoadOperation -(void)main { NSURL *url=[NSURL URLWithString:self.url]; NSData *data=[NSData dataWithContentsOfURL:url]; UIImage *imgae=[UIImage imageWithData:data]; NSLog(@"--%@--",[NSThread currentThread]); //图片下载完毕后,通知代理 if ([self.delegate respondsToSelector:@selector(downLoadOperation:didFishedDownLoad:)]) { dispatch_async(dispatch_get_main_queue(), ^{//回到主线程,传递数据给代理对象 [self.delegate downLoadOperation:self didFishedDownLoad:imgae]; }); } } @end
#import <UIKit/UIKit.h> @interface CustomOperationDemoViewController : UIViewController @end
#import "CustomOperationDemoViewController.h" #import "YYappModel.h" #import "YYdownLoadOperation.h" @interface CustomOperationDemoViewController () <YYdownLoadOperationDelegate,UITableViewDataSource,UITableViewDelegate> @property(nonatomic,strong)NSArray *apps; @property(nonatomic,strong)NSOperationQueue *queue; @property (nonatomic,strong) UITableView *tableView; @property(nonatomic,strong)NSMutableDictionary *operations; @property(nonatomic,strong)NSMutableDictionary *images; @end @implementation CustomOperationDemoViewController - (void)viewDidLoad { [super viewDidLoad]; [self.view addSubview:self.tableView]; [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(self.view); }]; // Do any additional setup after loading the view. } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } -(NSArray *)apps { if (_apps==nil) { NSString *path=[[NSBundle mainBundle]pathForResource:@"apps.plist" ofType:nil]; NSArray *tempArray=[NSArray arrayWithContentsOfFile:path]; //字典转模型 NSMutableArray *array=[NSMutableArray array]; for (NSDictionary *dict in tempArray) { YYappModel *app=[YYappModel appModelWithDict:dict]; [array addObject:app]; } _apps=array; } return _apps; } -(NSOperationQueue *)queue { if (_queue==Nil) { _queue=[[NSOperationQueue alloc]init]; //设置最大并发数为3 _queue.maxConcurrentOperationCount=3; } return _queue; } - (NSMutableDictionary *)images{ if (!_images) { _images = [NSMutableDictionary dictionary]; } return _images; } - (NSMutableDictionary *)operations{ if (!_operations) { _operations = [NSMutableDictionary dictionary]; } return _operations; } - (UITableView *)tableView{ if(!_tableView){ _tableView = [[UITableView alloc]init]; _tableView.dataSource =self; _tableView.delegate = self; } return _tableView; } #pragma mark-数据源方法 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.apps.count; } -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *ID=@"ID"; UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:ID]; if (cell==nil) { cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID]; } YYappModel *app=self.apps[indexPath.row]; cell.textLabel.text=app.name; cell.detailTextLabel.text=app.download; //保证一个url对应一个image对象 UIImage *image=self.images[app.icon]; if (image) {//缓存中有图片 cell.imageView.image=image; }else // 缓存中没有图片,得下载 { //先设置一张占位图片 cell.imageView.image=[UIImage imageNamed:@"57437179_42489b0"]; YYdownLoadOperation *operation=self.operations[app.icon]; if (operation) {//正在下载 //什么都不作 }else //当前没有下载,那就建立操做 { operation=[[YYdownLoadOperation alloc]init]; operation.url=app.icon; operation.indexPath=indexPath; operation.delegate=self; [self.queue addOperation:operation];//异步下载 self.operations[app.icon]=operation; } } return cell; } -(void)downLoadOperation:(YYdownLoadOperation *)operation didFishedDownLoad:(UIImage *)image { //1.移除执行完毕的操做 [self.operations removeObjectForKey:operation.url]; //2.将图片放到缓存中 self.images[operation.url]=image; //3.刷新表格(只刷新下载的那一行) [self.tableView reloadRowsAtIndexPaths:@[operation.indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; NSLog(@"--%d--%@--",operation.indexPath.row,[NSThread currentThread]); } @end
参考资料
iOS开发多线程篇—自定义NSOperation
http://www.cnblogs.com/wendingding/p/3811121.html
http://www.cnblogs.com/mjios/archive/2013/04/19/3029765.html
如何使用NSOperations和NSOperationQueues(二)
http://www.cocoachina.com/industry/20121010/4900.html