一、概念
NSOperation是一个多线程任务。NSOperation有NSInvocationOperation、NSBlockOperation两个子类。
NSOperationQueue负责管理多个NSOperation,它是个FIFO队列,会按顺序启动线程执行NSOperation任务。
二、用法
NSOperation实现多线程有两个方式,一个是直接使用NSInvocationOperation、NSBlockOperation两个子类,一个是自己实现NSOperation的子类。在平时的开发中掌握第一种的使用基本上能够应对大部分多线程需求。这里主要讲解第一种使用
一、直接使用NSInvocationOperation和NSBlockOperation
NSInvocationOperation 是通过方法实现的形式完成多线程任务。
NSInvocationOperation*invocationOperation = [[NSInvocationOperationalloc]initWithTarget:selfselector:@selector(invocationOperationAction)object:nil];
NSBlockOperation是通过代码块的形式完成多线程任务。
NSBlockOperation*blockOperation = [NSBlockOperationblockOperationWithBlock:^{
}];
执行任务有两个方式,一个是用start方法 一个是提交到NSOperationQueue, 用start 方法时与主线程同步,有阻塞主线程的情况,提交到NSOperationQueue中与主线程是异步,不会阻塞到主线程。
NSOperationQueue可以通过maxConcurrentOperationCount设置线程最大并行数量,为1的时候相当于串行,大于1时为并发。
Talk is Cheap,show you the code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
- (void)viewDidLoad { [superviewDidLoad]; UILabel*label= [[UILabelalloc]init]; label.frame=CGRectMake(40,40,100,20); label.text=@"页面已经显示"; [self.viewaddSubview:label]; self.imgView= [[UIImageViewalloc]init]; self.imgView.frame=CGRectMake(30,30,50,50); self.imgView.backgroundColor= [UIColorredColor]; [self.viewaddSubview:self.imgView]; NSInvocationOperation*invocationOperation = [[NSInvocationOperationalloc]initWithTarget:selfselector:@selector(invocationOperationAction)object:nil]; __weakViewController*weakSelf =self; NSBlockOperation*blockOperation = [NSBlockOperationblockOperationWithBlock:^{ for(inti =0; i <3; i++) { [NSThreadsleepForTimeInterval:0.5]; NSLog(@"线程block--%d",i); } //异步加载图片时要到主线程显示 NSURL*url = [NSURLURLWithString:@"https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1459910345&di=297c58ac877a35d5cd21f1b12e25ddf0&src=http://a.hiphotos.baidu.com/lvpics/w=1000/sign=c9a07988672762d0803ea0bf90dc09fa/359b033b5bb5c9ea7582c548d139b6003af3b32c.jpg"]; NSData*data = [[NSDataalloc]initWithContentsOfURL:url]; UIImage*img = [[UIImagealloc]initWithData:data]; if(img) { [weakSelfperformSelectorOnMainThread:@selector(updateImgView:)withObject:imgwaitUntilDone:YES]; } }]; //----------------执行任务方式一:用start方法------------------ /**用start执行线程任务时为同步效果,blockOperation、invocationOperation阻塞主线程 *要等到blockOperation、invocationOperation两个线程任务执行完毕之后self.view的背景色才会变为黄色 //*/ //NSLog(@"没有变色"); //这句话一开始就会打印出来,而label和imgView要等两个operation后才显示出来。因为UI要在主线程上渲染后显示,start阻塞了主线程。 //[blockOperation start]; //[invocationOperation start]; //NSLog(@"变色"); //self.view.backgroundColor = [UIColor yellowColor]; //---------------执行任务方式二:加入NSOperationQueue (两种方式运行的时候要注释掉其中一种) ----------- //线程任务与主线程异步,不会阻塞主线程,self.view的颜色一开始就变为黄色 NSOperationQueue*queue = [[NSOperationQueuealloc]init]; //设置最大的线程并行数量如果为1的话就相当于串行,大于1时为并行 queue.maxConcurrentOperationCount=2; [queueaddOperation:blockOperation]; [queueaddOperation:invocationOperation]; self.view.backgroundColor= [UIColoryellowColor]; } -(void)invocationOperationAction { for(inti =0; i <5; i++) { [NSThreadsleepForTimeInterval:0.5]; NSLog(@"线程invocation--%d",i); } } - (void)updateImgView:(UIImage*)image { self.imgView.image= image; } |
三、总结
1、有NSBlockOperation 和 NSInvocationOperation 两种方式实现多线程任务;
2、有两种方式执行任务 :一个是start方法,一个是提交到NSOperationQueue,前者是同步,后者是异步。
3、NSOperationQueue可以通过设置最大线程并发数量来决定串行或并发。