NSOperation的使用
NSOperation是个抽象类,并不具备封装操作的能力,必须使用它的子类,使用NSOperation子类的方式有3种
- NSBlockOperation
//1. 封装任务
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"1---%@", [NSThread currentThread]);
}];
//2.追加其它任务
//注意: 在没有队列的情况下, 如果给BlockOperation追加其它任务, 那么其它任务会在子线程中执行
[op1 addExecutionBlock:^{
NSLog(@"2---%@", [NSThread currentThread]);
}];
[op1 addExecutionBlock:^{
NSLog(@"3---%@", [NSThread currentThread]);
}];
//3.启动任务
[op1 start];
注意:
默认情况下,调用了start方法后并不会开一条新线程去执行操作,而是在当前线程同步执行操作,只有将NSOperation放到一个NSOperationQueue中,才会异步执行操作NSInvocationOperation
//1.封装任务
NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];
//2.要想执行任务必须调用start
[op1 start];
NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run2) object:nil];
[op2 start];
}
- (void)run
{
NSLog(@"%@", [NSThread currentThread]);
}
- (void)run2
{
NSLog(@"%@", [NSThread currentThread]);
}
- 自定义NSOperation
自定义NSOperation的步骤:
自定义一个继承自NSOperation的子类,并重写- (void)main方法,在里面实现想执行的任务.
只要将任务添加到队列中, 那么队列在执行自定义任务的时候,就会自动调用main方法
//1.创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//2.创建任务
//自定义任务的好处: 提高代码的复用性
YFYOperation *op1 = [[YFYOperation alloc] init];
YFYOperation *op2 = [[YFYOperation alloc] init];
//3.添加任务到队列
[queue addOperation:op1];
[queue addOperation:op2];
- 重写
- (void)main
方法的注意点:
自己创建自动释放池(因为如果是异步操作,无法访问主线程的自动释 放池)
经常通过- (BOOL)isCancelled
方法检测操作是否被取消,对取消做出响应
NSOperationQueue
- NSOperationQueue的作用
NSOperation可以调用start方法来执行任务,但默认是同步执行的,如果将NSOperation添加到NSOperationQueue(操作队列)中,系统会自动异步执行NSOperation中的操作 - NSOperationQueue与NSBlockOperation
//1.创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//2.创建任务
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"1 == %@", [NSThread currentThread]);
}];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"2 == %@", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"3 == %@", [NSThread currentThread]);
}];
/*如果是使用block来封装任务, 那么有一种更简便的方法,只要利用队列调用addOperationWithBlock:方法, 系统内部会自动封装成一个NSBlockOperation,然后再添加到队列中*/
// 3.添加任务到队列
[queue addOperation:op1];
[queue addOperation:op2];
- NSOperationQueue与 NSInvocationOperation
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//2.创建任务
//只要是自己创建的队列, 就会在子线程中执行,而且默认就是并发执行
NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download1) object:nil];
NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download2) object:nil];
//3.添加任务到队列中,只要将任务添加到队列中, 队列会自动调用start
[queue addOperation:op1];
[queue addOperation:op2];
- (void)download1
{
NSLog(@"1 == %@", [NSThread currentThread]);
}
- (void)download2
{
NSLog(@"2 == %@", [NSThread currentThread]);
}
最大并发数
什么是并发数?
同时执行的任务数,比如,同时开3个线程执行3个任务,并发数就是3最大并发数的相关方法:
- (NSInteger)maxConcurrentOperationCount;
- (void)setMaxConcurrentOperationCount:(NSInteger)cnt;
自己创建的队列默认是并发, 如果设置
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 1;
//就是串行注意: 不能设置为0, 如果设置为0就不执行任务,
默认情况下maxConcurrentOperationCount = -1
在开发中并发数最多尽量不要超过5~6条
队列的取消、暂停、恢复
- 只要设置队列的suspended为YES, 那么就会暂停队列中其它任务的执行
self.queue.suspended = YES;
也就是说不会再继续执行没有执行到得任务 - 注意: 设置为暂停之后, 不会立即暂停,会继续执行当前正在执行的任务, 直到当前任务执行完毕, 就不会执行下一个任务了,也就是说, 暂停其实是暂停下一个任务, 而不能暂停当前任务
- 注意: 暂停是可以恢复的,只要设置队列的suspended为NO, 那么就会恢复队列中其它任务的执行
- 取消队列中所有的任务的执行
[self.queue cancelAllOperations];
取消和暂停一样, 是取消后面的任务, 不能取消当前正在执行的任务 - 注意: 取消是不可以恢复的
操作依赖
- NSOperation之间可以设置依赖来保证执行顺序,比如一定要让操作A执行完后,才能执行操作B,可以这么写
[operationB addDependency:operationA];
// 操作B依赖于操作A - 注意:不能相互依赖,比如A依赖B,B依赖A.
- 可以在不同queue的NSOperation之间创建依赖关系
// 1.创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSOperationQueue *queue2 = [[NSOperationQueue alloc] init];
// 2.创建任务
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"1-------%@", [NSThread currentThread]);
}];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"2-------%@", [NSThread currentThread]);
}];
NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"3-------%@", [NSThread currentThread]);
}];
NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"4-------%@", [NSThread currentThread]);
for (int i = 0; i < 1000; i++) {
NSLog(@"%i", i);
}
}];
NSBlockOperation *op5 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"5-------%@", [NSThread currentThread]);
}];
// 3.添加依赖
[op5 addDependency:op1];
[op5 addDependency:op2];
[op5 addDependency:op3];
[op5 addDependency:op4];
// 4.监听op4什么时候执行完毕
op4.completionBlock = ^{
NSLog(@"op4中所有的操作都执行完毕了");
};
// 5.添加任务到队列
[queue addOperation:op1];
[queue addOperation:op2];
[queue2 addOperation:op3];
[queue2 addOperation:op4];
[queue addOperation:op5];