NSOperation实现流程:
只要将NSOperation放入NSOperationQueue线程队列中,就会启动执行。
NSOperation是个抽象类,并不具备封装操作的能力,必须使用它的子类
使用NSOperation子类的方式有3种
1.NSInvocationOperation
1 创建Invocation线程
NSInvocationOperation *invocationOperation =[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(loadImage)object:nil];
// 注意如果直接调用start方法,则此操作会在主线程中调用
// [invocationOperation start];//一般不会这么操作,而是添加到NSOperationQueue中
//创建线程队列
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
operationQueue.maxConcurrentOperationCount = 5; //设置最大并发线程数
//注意添加到线程队列后,队列里的线程就会开始执行
[operationQueue addOperation:invocationOperation];// 这里面就自动开始start 调用
补充:创建队列注意点:
GCD: 串行类型:create & 主队列
并发类型:create & 全局并发队列
NSOperation:
主队列: [NSOperationQueue mainQueue] 和GCD中的主队列一样,串行队列
非主队列: [[NSOperationQueue alloc]init] 非常特殊(同时具备并发和串行的功能)
默认情况下,非主队列是并发队列
2.NSBlockOperation
方法一:创建Block线程
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
NSBlockOperation * blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{ }];
[operationQueue addOperation:blockOperation1];
NSBlockOperation * blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{ }];
[operationQueue addOperation:blockOperation1];
方法二:创建Block线程
NSOperationQueue * operationQueue = [[NSOperationQueue alloc] init];
[operationQueue addOperationWithBlock:^{ }];
补充: NSBlockOperation可以实现追加任务
给blockOperation 追加任务.
[blockOperation2 addExecutionBlock:^{NSLog(@"4----%@",[NSThread currentThread]);}];
[blockOperation2 addExecutionBlock:^{NSLog(@"5----%@",[NSThread currentThread]);}];
[blockOperation2 addExecutionBlock:^{NSLog(@"6----%@",[NSThread currentThread]);}];
3.自定义子类继承NSOperation,实现内部相应的方
创建一个 @interface LPOperation : NSOperation 继承NSOperation 的函数.
自定义子类NSOperation常用函数场景
场景一 : 可以用到大文件下载时候,比如说下载暂停,取消,开始,
// 暂停,是可以恢复 [self.queue setSuspended:YES];
// 继续执行 [self.queue setSuspended:NO];
// 取消,不可以恢复 [self.queue cancelAllOperations];//该方法内部调用了所有操作的cancel方法
if(self.isCancelled) return;
NSLog(@"+++++++++++++++");
for (NSInteger i = 0; i<1000;i++ ) {
NSLog(@"download2---%zd--%@",i,[NSThread currentThread]);
}
场景二: NSOperation操作依赖和监听
- (void)loadImageWithMultiThread{
int count = 9;
NSOperationQueue *operationQueue = [[NSOperationQueue alloc]init];
operationQueue.maxConcurrentOperationCount = 5;//设置最大并发线程数
//创建加载最后一张图片的线程
NSBlockOperation *lastBlockOperation = [NSBlockOperation blockOperationWithBlock:^{
[self loadImage:[NSNumber numberWithInt:(count-1)]];(调用下载函数)
}];
//创建多个线程用于下载其他图片
for (int i=0; i < count -1 , i++){
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
[self loadImage:[NSNumber numberWithInt:i]];
}];
//设置依赖操作为最后一张图片加载操作,只有最后一张图片加载完成,其他图片才 开始陆续加载
[blockOperation addDependency:lastBlockOperation];//这句话的意思就是lastBlockOperation这个操作依赖blockOperation这个操作,等blockOperation完成之后才调用.
[operationQueue addOperation:blockOperation];
}
//将最后一个图片的加载线程加入线程队列
[operationQueue addOperation:lastBlockOperation];
}
补充:操作监听 ,当blockOperation 完成时候再调用这个函数,但是不是立即调用,因为是多线程是无序的,只是代表blockOperation 的操作下一步会掉那个到任务中.
blockOperation.completionBlock = ^{
NSLog(@"++++客官,来看我吧------%@",[NSThread currentThread]);
};
NSOperation 线程间的通信
需求案例:
1.下载图片1
2.下载图片2
3.合并图片
-(void)comBie
{
//1.创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
__block UIImage *image1;
__block UIImage *image2;
//2 封装操作,下载图片1
NSBlockOperation *download1 = [NSBlockOperation blockOperationWithBlock:^{
NSURL *url = [NSURL URLWithString:@"http://s15.sinaimg.cn/bmiddle/4c0b78455061c1b7f1d0e"];
NSData *imageData = [NSData dataWithContentsOfURL:url];
image1 = [UIImage imageWithData:imageData];
NSLog(@"download---%@",[NSThread currentThread]);
}];
//3 封装操作,下载图片2
NSBlockOperation *download2 = [NSBlockOperation blockOperationWithBlock:^{
NSURL *url = [NSURL URLWithString:@"http://www.027art.com/feizhuliu/UploadFiles_6650/201109/2011091718442835.jpg"];
NSData *imageData = [NSData dataWithContentsOfURL:url];
image2 = [UIImage imageWithData:imageData];
NSLog(@"download---%@",[NSThread currentThread]);
}];
//4.封装合并图片的操作
NSBlockOperation *combie = [NSBlockOperation blockOperationWithBlock:^{
//4.1 开上下文
UIGraphicsBeginImageContext(CGSizeMake(200, 200));
//4.2 画图1
[image1 drawInRect:CGRectMake(0, 0, 100, 200)];
//4.3 画图2
[image2 drawInRect:CGRectMake(100, 0, 100, 200)];
//4.4 根据上下文得到图片
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
//4.5 关闭上下文
UIGraphicsEndImageContext();
//7.更新UI
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
self.imageView.image = image;
NSLog(@"UI----%@",[NSThread currentThread]);
}];
}];
//5.设置依赖关系
[combie addDependency:download1];
[combie addDependency:download2];
//6.添加操作到队列中
[queue addOperation:download2];
[queue addOperation:download1];
[queue addOperation:combie];
}
网友评论