(一)NSThread (二)Cocoa NSOperation (三)GCD(全称:Grand Central Dispatch)
Grand Central dispatch(GCD)是Apple开发的一个多核编程的解决方案。在iOS4.0开始之后才能使用。GCD是一个替代NSThread, NSOperationQueue,NSInvocationOperation等技术的很高效强大的技术。
下面我用简单易于理解的代码实例来介绍NSThread在开发实践中的使用,具体使用时可以根据实际情况进行扩展:
一、NSThread的使用(基本已过时)
#import <UIKit/UIKit.h> #define kURL @"http://www.iyi8.com/uploadfile/2014/0506/20140506085929652.jpg" @interface ViewController : UIViewController @end
#import "ViewController.h" @interface ViewController () { UIImage *_image; UIImageView *_imageView; int _tickets; int _count; NSThread *_threadOne; NSThread *_threadTwo; NSThread *_threadThree; NSCondition *_condition; NSLock *_lock; } @end @implementation ViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { } return self; }
- (void)loadView { self.view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)]; NSLog(@"klfaklfa ------ - - "); _imageView = [[UIImageView alloc] initWithFrame:CGRectMake(100, 100, 100, 150)]; [self.view addSubview:_imageView]; }
- (void)viewDidLoad { [super viewDidLoad]; _tickets = 200; _count = 0; _lock = [[NSLock alloc] init]; //锁对象 _condition = [[NSCondition alloc] init]; //线程1 _threadOne = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil]; _threadOne.name = @"thread-1"; [_threadOne start]; //线程2 _threadTwo = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil]; _threadTwo.name = @"thread-2"; [_threadTwo start]; //线程3 _threadThree = [[NSThread alloc] initWithTarget:self selector:@selector(run3) object:nil]; _threadThree.name = @"thread-3"; [_threadThree start]; //如果没有线程同步的lock,物品售出数量就会出现重复导致数据竞争不同步问题.加上lock之后线程同步保证了数据的正确性。 [NSThread detachNewThreadSelector:@selector(downloadImage:) toTarget:self withObject:kURL]; NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(downloadImage:) object:kURL]; [thread start]; }
/** 测试NSOperationQueue使用
*/
- (void)viewDidLoad { [super viewDidLoad]; NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadImage:) object:kURL]; NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [queue addOperation:operation]; }
- [queue setMaxConcurrentOperationCount:5];
/** 测试GCD的dispatch_async使用*/
- (void)viewDidLoad { [super viewDidLoad]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSURL * url = [NSURL URLWithString:<span>kURL</span>]; NSData * data = [[NSData alloc]initWithContentsOfURL:url]; UIImage *image = [[UIImage alloc]initWithData:data]; if (data != nil) { dispatch_async(dispatch_get_main_queue(), ^{ _imageView.image = image; }); } }); }
/** 测试GCD的dispatch_group_async使用*/
- (void)viewDidLoad { [super viewDidLoad]; //此方法可以实现监听一组任务是否完成,如果完成后通知其他操作(如界面更新),此方法在下载附件时挺有用, //在搪行几个下载任务时,当下载完成后通过dispatch_group_notify通知主线程下载完成并更新相应界面 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, queue, ^{ [NSThread sleepForTimeInterval:0.09]; NSLog(@"group1"); NSURL * url = [NSURL URLWithString:kURL]; NSData * data = [[NSData alloc]initWithContentsOfURL:url]; _image = [[UIImage alloc]initWithData:data]; }); dispatch_group_async(group, queue, ^{ [NSThread sleepForTimeInterval:0.09]; NSLog(@"group2"); }); dispatch_group_async(group, queue, ^{ [NSThread sleepForTimeInterval:0.09]; NSLog(@"group3"); }); dispatch_group_notify(group, dispatch_get_main_queue(), ^{ NSLog(@"updateUi"); _imageView.image = _image; }); }
/** 测试GCD的dispatch_barrier_async使用*/
- (void)viewDidLoad { [super viewDidLoad]; //是在前面的任务执行结束后它才执行,而且它后面的任务等它执行完成之后才会执行 dispatch_queue_t queue = dispatch_queue_create("gcd.devdiy.com", DISPATCH_QUEUE_CONCURRENT); dispatch_async(queue, ^{ [NSThread sleepForTimeInterval:2]; NSLog(@"dispatch_async1"); }); dispatch_async(queue, ^{ [NSThread sleepForTimeInterval:4]; NSLog(@"dispatch_async2"); }); dispatch_barrier_async(queue, ^{ NSLog(@"dispatch_barrier_async"); [NSThread sleepForTimeInterval:4]; }); dispatch_async(queue, ^{ [NSThread sleepForTimeInterval:1]; NSLog(@"dispatch_async"); }); }
- (void)run3 { while (true) { [_condition lock]; [NSThread sleepForTimeInterval:3]; NSLog(@"当前物品名称:%d,售出数量:%d,线程名-=-==: %@", _tickets, _count, [[NSThread currentThread] name]); [_condition signal]; [_condition unlock]; } } - (void)run { while (true) { //上锁 [_lock lock]; if (_tickets > 0) { [NSThread sleepForTimeInterval:0.09]; _count = 200 - _tickets; NSLog(@"当前物品名称:%d,售出数量:%d,线程名: %@", _tickets, _count, [[NSThread currentThread] name]); _tickets--; }else{ break; } [_lock unlock]; } } /** * @param string url */ - (void)downloadImage:(NSString *) url{ NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]]; UIImage *image = [[UIImage alloc] initWithData:data]; if(image == nil){ [self updateUI:image]; }else{ [self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES]; } } - (void)updateUI:(UIImage *)image { _imageView.image = image; } @end