- (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