一、概念
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:
- (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可以通過設置最大線程并發數量來決定串行或并發。