NSOperationQueue操作队列 + NSOperation子类操作(多个,可以设置操作之间依赖关系)
操作子类:NSInvocationOperation、NSBlockOperation
添加操作方法:addOperation 、addOperationWithBlock
推荐前往
将一个NSOperation(实际开中需要使用其子类NSInvocationOperation、NSBlockOperation)放到NSOperationQueue这个队列中线程就会依次启动。NSOperationQueue负责管理、执行所有的NSOperation,在这个过程中可以更加容易的管理线程总数和控制线程之间的依赖关系。
NSOperation有两个常用子类用于创建线程操作:NSInvocationOperation和NSBlockOperation,两种方式本质没有区别,但是是后者使用Block形式进行代码组织,使用相对方便。
NSInvocationOperation
整个过程就是:创建一个操作,在这个操作中指定调用方法和参数,然后加入到操作队列。
NSInvocationOperation *invocationOperation=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(loadImage) object:nil];
//创建完NSInvocationOperation对象并不会调用,它由一个start方法启动操作,但是注意如果直接调用start方法,则此操作会在主线程中调用,一般不会这么操作,而是添加到NSOperationQueue中
// [invocationOperation start];
//创建操作队列
NSOperationQueue *operationQueue=[[NSOperationQueue alloc]init];
//注意添加到操作队后,队列会开启一个线程执行此操作
[operationQueue addOperation:invocationOperation];
NSBlockOperation
//创建操作队列
NSOperationQueue *operationQueue=[[NSOperationQueue alloc]init];
operationQueue.maxConcurrentOperationCount=5;//设置最大并发线程数
//创建多个线程用于填充图片
for (int i=0; i<count; ++i) {
//方法1:创建操作块添加到队列
// //创建多线程操作
// NSBlockOperation *blockOperation=[NSBlockOperation blockOperationWithBlock:^{
// [self loadImage:[NSNumber numberWithInt:i]];
// }];
// //创建操作队列
//
// [operationQueue addOperation:blockOperation];
//方法2:直接使用操队列添加操作
[operationQueue addOperationWithBlock:^{
[self loadImage:[NSNumber numberWithInt:i]];
}];
操作依赖执行顺序
前面使用NSThread很难控制线程的执行顺序,但是使用NSOperation就容易多了,每个NSOperation可以设置依赖线程。假设操作A依赖于操作B,线程操作队列在启动线程时就会首先执行B操作,然后执行A。
-(void)loadImageWithMultiThread{
int count=ROW_COUNT*COLUMN_COUNT;
//创建操作队列
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) {
//方法1:创建操作块添加到队列
//创建多线程操作
NSBlockOperation *blockOperation=[NSBlockOperation blockOperationWithBlock:^{
[self loadImage:[NSNumber numberWithInt:i]];
}];
//设置依赖操作为最后一张图片加载操作
[blockOperation addDependency:lastBlockOperation];
[operationQueue addOperation:blockOperation];
}
//将最后一个图片的加载操作加入线程队列
[operationQueue addOperation:lastBlockOperation];
}
可以看到虽然加载最后一张图片的操作最后被加入到操作队列,但是它却是被第一个执行的。操作依赖关系可以设置多个,例如A依赖于B、B依赖于C…但是千万不要设置为循环依赖关系(例如A依赖于B,B依赖于C,C又依赖于A),否则是不会被执行的。