GCD的操作不受人为控制,NSOpertion可以控制操作的暂停,取消,添加.
1.是一个抽象的类,不能直接使用.只有定义,没有实现.
2. 作为父类,约束子类的一些共有的属性和方法
3. 两个子类:
NSInvocationOperation
NSBlockOperation
4. 队列 : NSOperationQueue,默认是并发队列;
5. OP的核心 : 将操作添加到队列中
两种写法:1---这种写法不能获取操作对象
[self.queueaddOperationWithBlock:^{
// 查看当前的线程
NSLog(@"%d %@",i,[NSThreadcurrentThread]);
}];
方法2------------
NSOperationQueue *queue = [[NSOperationQueuealloc]init];
// 子类NSBlockOperation创建操作对象 :默认是异步的
NSBlockOperation *op = [NSBlockOperationblockOperationWithBlock:^{
// 查看当前的线程
NSLog(@"%@",[NSThreadcurrentThread]);
}];
// 将操作添加到队列
[queue addOperation:op];
//子类 NSInvocationOperation创建操作对象
NSInvocationOperation *op = [[NSInvocationOperationalloc]initWithTarget:selfselector:@selector(demo:)object:nil];
// 创建队列
NSOperationQueue *queue = [[NSOperationQueuealloc]init];
// 将操作对象添加到队列
[queue addOperation:op];
6. GCD的核心 : 将任务添加到队列
7.NSOperationQueue的操作默认是异步的,会开启新线程,
8. 回到主线程更新UI
[[NSOperationQueuemainQueue]addOperationWithBlock:^{
// 查看当前的线程
NSLog(@"更新UI...%@",[NSThreadcurrentThread]);
}];
间接控制了线程的数量,最少2个线程.但是不会开太多
[[NSOperationQueue alloc] init].maxConcurrentOperationCount = 2;
或者
[[[NSOperationQueue alloc] init] setMaxConcurrentOperationCount:2];
注意:操作对象默认在主线程中执行,只有添加到队列中才会开启新的线程。即默认情况下,如果操作没有放到队列中queue中,都是同步执行。只有将NSOperation放到一个NSOperationQueue中,才会异步执行操作
10.暂停队列
// 表示队列"暂时"不能调度操作执行
// 正在执行的操作不能被暂停
// operationCount : 表示队列中的操作个数
// 计算的是队列中正在执行和,没有执行的操作的总个数.执行完成的操作不会计算在内
// 注意 :不要先暂停队列,一旦先暂停了队列,那么队列是不会去调度操作执行的
self.queue.suspended =YES;
//取消队列中的全部操作 :正在执行的操作是无法取消的
// 如果想取消需要自定义NSOperation
// 类似于字典中移除全部的对象
// 调用这个方法,表示队列向队列中的所有操作发送cancel消息
// 这个方法有延迟时间
[self.queue cancelAllOperations];
12.设置操做的优先级 :优先级最高
// 同样的不能够决定操作的执行的先后顺序.决定这个操作有更多的机会被调度执行
op1.qualityOfService =NSQualityOfServiceUserInteractive;
// NSQualityOfServiceBackground优先级最低
op2.qualityOfService =NSQualityOfServiceBackground;
13.// 监听操作是否执行结束 ,如果结束会调用这个方法:这个操作是在子线程执行的
[op1 setCompletionBlock:^{
// 查看当前的线程
NSLog(@"操作执行结束 %@",[NSThreadcurrentThread]);
}];
13.操作间的依赖
// 创建登陆操作
NSBlockOperation *op1 = [NSBlockOperationblockOperationWithBlock:^{
// 查看当前的线程
NSLog(@"登陆 %@",[NSThreadcurrentThread]);
}];
// 创建付费操作
NSBlockOperation *op2 = [NSBlockOperationblockOperationWithBlock:^{
// 查看当前的线程
NSLog(@"付费 %@",[NSThreadcurrentThread]);
}];
// 创建下载操作
NSBlockOperation *op3 = [NSBlockOperationblockOperationWithBlock:^{
// 查看当前的线程
NSLog(@"下载 %@",[NSThreadcurrentThread]);
}];
// 创建通知用户的操作
NSBlockOperation *op4 = [NSBlockOperationblockOperationWithBlock:^{
// 查看当前的线程
NSLog(@"通知用户 %@",[NSThreadcurrentThread]);
}];
// 建立依赖关系
// 付费依赖登陆
[op2 addDependency:op1];
// 下载依赖付费
[op3 addDependency:op2];
// 通知用户依赖下载
[op4 addDependency:op3];
//登陆是不需要依赖任何操作的
// 如果登陆依赖通知用户,就是循环依赖,此时,队列是不会调度任务执行的
// 注意 : 绝对不能做
// [op1 addDependency:op4];
// 统一的将操作添加到队列
// waitUntilFinished : 表示是否等待前面的任务执行结束,在执行后面的任务
[self.queueaddOperations:@[op1,op2,op3]waitUntilFinished:NO];
// 将通知用户的操作添加到主队列中
// 操作间的依赖是可以跨队列建立的
[[NSOperationQueuemainQueue]addOperation:op4];
// 注意 :千万不要在添加到队列之后,再建立依赖关系,因为队列已经在调度任务执行了