多线程NSThread的使用
#import <UIKit/UIKit.h> @interface UIImageView (cache) //为UIImageView写一个添加网络图片的方法 - (void)setimage:(NSString *)str; @end
#import "UIImageView+cache.h" @implementation UIImageView (cache) //如果这样直接写方法,在主线程,当我们在加载网络时不能滑动TextView - (void)setimage:(NSString *)str { NSURL *url = [NSURL URLWithString:str]; NSData *data = [NSData dataWithContentsOfURL:url]; self.image = [UIImage imageWithData:data]; } @end
#import "ViewController.h" #import "UIImageView+cache.h" @interface ViewController () { UIImageView *_image; NSMutableArray *arr; } - (IBAction)click:(UIButton *)sender; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; arr = [NSMutableArray array]; //创建八行六列的UIImageView for (int i = 0; i < 6; i ++) { for (int j = 0 ; j < 8; j ++) { _image = [[UIImageView alloc]initWithFrame:CGRectMake(i * 62, j * 62 , 60, 60)]; _image.backgroundColor = [UIColor yellowColor]; [self.view addSubview:_image]; //将创建好的UIImageView放进可变数组。 [arr addObject:_image]; } } } - (IBAction)click:(UIButton *)sender { for (UIImageView *imageview in arr) { //利用分类给数组里的UIImageView添加图片 [imageview setimage:@"http://img31.mtime.cn/pi/2013/03/08/144644.81111130_1280X720.jpg"]; } } @end
- (void)setimage:(NSString *)str { //开启一个多线程,并且把str通过创建多线程传递到多线程的任务中(注:这里的字符串为网络图片的地址) [NSThread detachNewThreadSelector:@selector(thredAction:) toTarget:self withObject:str]; } //多线程的任务 - (void)thredAction:(NSString *)str { //将字符串转换成URL NSURL *url = [NSURL URLWithString:str]; //将url转化成data NSData *data = [NSData dataWithContentsOfURL:url]; //注意:UI的修改只能放在主线程 所以写在这里还是错误 //self.image = [UIImage imageWithData:data]; //回到主线程 [self performSelectorOnMainThread:@selector(setImage:) withObject:[UIImage imageWithData:data] waitUntilDone:YES]; }
//创建线程队列 NSOperationQueue *queue = [[NSOperationQueue alloc]init]; //关闭暂停队列,用于让所有的线程加入队列后在执行任务 [queue setSuspended:YES]; //设置最大并发数, queue.maxConcurrentOperationCount = 2; //创建线程 NSInvocationOperation *operation1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(operation1:) object:@"operation1"]; //设置线程优先级 operation1.queuePriority = NSOperationQueuePriorityNormal; //创建第二个线程 NSInvocationOperation *operation2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(operation2:) object:@"operation2"]; //设置线程优先级 operation2.queuePriority = NSOperationQueuePriorityVeryHigh; //将线程加入队列 [queue addOperation:operation1]; [queue addOperation:operation2]; //用Block创建多线程 [queue addOperationWithBlock:^{ //注意这里我们要将任务放进自动释放池,因为这段代码不在(主线程)中 @autoreleasepool { for (int i = 0; i < 10; i ++) { NSLog(@"operation3%d",i); } } }]; //开始队列 [queue setSuspended:NO];
#import "UIImageView+cache.h" @implementation UIImageView (cache) - (void)setImages:(NSString *)str { //创建队列 NSOperationQueue *queue = [[NSOperationQueue alloc]init]; //设置最大并发 queue.maxConcurrentOperationCount = 1; //创建线程 NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(operationAction:) object:str]; //将线程加入线程队列 [queue addOperation:operation]; } - (void)operationAction:(NSString *)str { NSURL *url = [NSURL URLWithString:str]; NSData *data = [NSData dataWithContentsOfURL:url]; //在这里我们要修改UI了所以要重新回到主线程 //第一种回主线程的方式 [self performSelectorOnMainThread:@selector(setImage:) withObject:[UIImage imageWithData:data] waitUntilDone:YES]; /* //第二种方式回到主线程 [[NSOperationQueue mainQueue] addOperationWithBlock:^{ self.image = [UIImage imageWithData:data]; }]; */ } @end viewController中的代码: #import "ViewController.h" #import "UIImageView+cache.h" @interface ViewController () @property (nonatomic, strong)NSMutableArray *dataArr; @end @implementation ViewController - (NSMutableArray *)dataArr { if (_dataArr == nil) { _dataArr = [NSMutableArray array]; return _dataArr; } return _dataArr; } - (void)viewDidLoad { [super viewDidLoad]; for (int i = 0; i < 8; i ++) { for (int j = 0; j < 6; j ++) { UIImageView *imageview = [[UIImageView alloc]initWithFrame:CGRectMake(j * 64, i * 80, 60, 75)]; imageview.backgroundColor = [UIColor yellowColor]; [self.view addSubview:imageview]; [self.dataArr addObject:imageview]; } } } - (IBAction)click:(UIButton *)sender { for (UIImageView *imageview in self.dataArr) { [imageview setImages:@"http://img31.mtime.cn/pi/2013/03/08/144644.81111130_1280X720.jpg"]; } } @end
#import "ViewController.h" @interface ViewController () @end @implementation ViewController /* //写之前,再来温习温习。 GCD的使用: 一 :队列 1.串行队列:添加到队列中的任务是一个一个执行的 2.并发(行)队列:添加到队列中的任务是多个同时执行的 3.主队列:里面的任务都是在主线程执行的。 4.全局队列:并行(发)队列 二:同步、异步 1、同步:需要后面的任务等待,不会开启新的线程,会直接使用当前的线程 2、异步:不需要后面的任务等待,会开启新的线程 */ - (void)viewDidLoad { dispatch_sync(queue2, ^{ @autoreleasepool { for (int i = 0; i < 50 ;i ++) { NSLog(@"1---------1"); } } }); dispatch_sync(queue2, ^{ @autoreleasepool { for (int i = 0; i < 50 ;i ++) { NSLog(@"2---------2"); } } });
通过以上分析我们可以看出: /*---------创建串行----------*/ dispatch_queue_t queue = dispatch_queue_create("queue3", DISPATCH_QUEUE_SERIAL); //向串行队列异步添加任务 dispatch_async(queue, ^{ for (int i=0; i<50; i++) { NSLog(@"🐷....i:%d",i); } }); dispatch_async(queue, ^{ for (int i=0; i<50; i++) { NSLog(@"🐶....i:%d",i); } });
尽管是异步添加任务,但是该队列是串行队列,所以猪 先被执行,然后才执行狗。 不难看出猫与(狗和猪)是同时执行的。而(猪和狗)则是猪先执行,狗在执行。例如猪和狗排了一个队,而猫自己排了一个队。 dispatch_sync(queue, ^{ for (int i=0; i<50; i++) { NSLog(@"🐶....i:%d",i); } }); dispatch_sync(queue, ^{ for (int i=0; i<100; i++) { NSLog(@"🐱....i:%d",i); } }); for (int i=0; i<100; i++) { NSLog(@"🐷....i:%d",i); }
NSLog(@"任务开始啦!!!"); //同步添加任务 dispatch_sync(mainQueue, ^{ NSLog(@"任务添加"); }); NSLog(@"结束");
|