NSOpertaion
也是并行变成技术
那和GCD
一样也有任务和队列的概念
NSOpertaion
本质上是对GCD
面向对象的封装
NSOpertaion
的核心概念:将操作
添加到队列
,操作
其实就是一段代码,
操作
:异步执行任务
队列
:GCD
并发队列
GCD
的核心概念:将任务
添加到队列
,任务
其实就是block
块
NSOpertaion
类 是一个抽象类
特点
- 不能直接使用的
- 定义子类共有的属性和方法
NSOpertaion
的子类
- NSInvocationOperation
- NSBlockOperation
关于创建线程
NSInvocationOperation * op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(threadTest) object:nil];
// start 会在当前线程调度任务
//[op start];
NSOperationQueue * queue = [[NSOperationQueue alloc] init];
//将操作添加到队列 这种添加方法默认会自动异步执行调度方法 队列也是默认为并发队列
[queue addOperation:op];
NSOperationQueue * queue2 = [[NSOperationQueue alloc] init];
NSBlockOperation * op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"block=%@",[NSThread currentThread]);
}];
[queue2 addOperation:op2];
NSOperationQueue * queue3 = [[NSOperationQueue alloc] init];
[queue3 addOperationWithBlock:^{
NSLog(@"queue3=%@",[NSThread currentThread]);
}];
常用事例
[queue3 addOperationWithBlock:^{
//异步操作
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
//更新ui
}];
}];
NSOpertaion
和GCD
对比
-
GCD
在iOS 4.0
推出,主要针对多核做了优化的并发技术,是C
语言 -
GCD
将任务
(block)添加到队列(串行/并发/主队列/全部队列
),并且指定执行任务的函数(同步/异步
) -
NSOpertaion
在iOS 2.0
推出的,苹果公司在推出GCD
之后对NSOpertaion
进行的重写,对GCD
面向对象的封装 -
NSOpertaion
将操作(异步执行的任务
) 添加到(并发队列
),就会立刻的异步
执行 -
GCD
提供了一些NSOpertaion
不具备的功能:一次执行
,延迟执行
,调度组
(op 中可以做到,有点麻烦) -
NSOpertaion
提供了一些GCD
实现起来比较困难的功能:最大的并发数
队列的暂停/继续
取消所有的操作
指定操作之间的依赖关系
NSOpertaion
的一些操作
设置最大同时并发数量
/**
最大并发数
*/
-(void)demo1{
// <#
//#>
self.opQueue.maxConcurrentOperationCount = 2;
for (int i =0; i<10; i++) {
[self.opQueue addOperationWithBlock:^{
NSLog(@"%d %@",i,[NSThread currentThread]);
}];
}
/*
没有设置并发数之前 开启了六条线程
0 <NSThread: 0x60c000067c00>{number = 3, name = (null)}
1 <NSThread: 0x600000261a40>{number = 4, name = (null)}
2 <NSThread: 0x60800026acc0>{number = 5, name = (null)}
3 <NSThread: 0x60c00006c540>{number = 6, name = (null)}
4 <NSThread: 0x600000262500>{number = 7, name = (null)}
5 <NSThread: 0x60c000067c00>{number = 3, name = (null)}
6 <NSThread: 0x60800026d340>{number = 8, name = (null)}
7 <NSThread: 0x60800026acc0>{number = 5, name = (null)}
8 <NSThread: 0x600000261a40>{number = 4, name = (null)}
9 <NSThread: 0x60c00006c540>{number = 6, name = (null)}
设置最大并发数之后 可能有人会觉得设置的是2 怎么这里有3条线程, 请注意 我们设置的是同时最大的并发操作数量,重点在同时,因为比如 开启了 3 4 但是有时任务被执行完了,3可能就会被线程池回收了
1 <NSThread: 0x60400007e6c0>{number = 4, name = (null)}
0 <NSThread: 0x60000006db00>{number = 3, name = (null)}
2 <NSThread: 0x60400007e6c0>{number = 4, name = (null)}
3 <NSThread: 0x60400007ca40>{number = 5, name = (null)}
4 <NSThread: 0x60000006db00>{number = 3, name = (null)}
5 <NSThread: 0x60400007ca40>{number = 5, name = (null)}
6 <NSThread: 0x60000006db00>{number = 3, name = (null)}
7 <NSThread: 0x60400007ca40>{number = 5, name = (null)}
8 <NSThread: 0x60400007e6c0>{number = 4, name = (null)}
9 <NSThread: 0x60400007ca40>{number = 5, name = (null)}
*/
}
队列挂起和取消所有操作
任务还是如上的demo1
- (IBAction)pause:(UIButton *)sender {
/*
判断队列是否挂起,队列里面有很多操作,如果队列挂起了,那么将不会从队列那操作出来执行,但是之前已经拿出来的操作将继续执行
挂起队列的时候,已经从队列拿出来的操作不会暂停
*/
if (self.opQueue.isSuspended) {
NSLog(@"继续");
self.opQueue.suspended = NO;
}
else{
NSLog(@"暂停");
self.opQueue.suspended = YES;
}
/*
0 <NSThread: 0x6000000734c0>{number = 4, name = (null)}
1 <NSThread: 0x60800006cb00>{number = 3, name = (null)}
3 <NSThread: 0x60800006cb00>{number = 3, name = (null)}
2 <NSThread: 0x608000072000>{number = 5, name = (null)}
暂停
4 <NSThread: 0x60c00046cf80>{number = 6, name = (null)}
5 <NSThread: 0x60800006cb00>{number = 3, name = (null)}
*/
/*
暂停之后还执行了 3 6 说明挂起队列的时候,已经从队列拿出来的操作不会暂停
*/
}
//队列当前包含的操作数
self.opQueue.operationCount
//决定队列的暂停和继续
self.opQueue.isSuspended
/*
1.队列挂起的时候,不会清空队列所有的操作,只有在队列继续的时候才会清空(比如,我先把队列暂停了,然后清空所有操作,这会儿不会清空队列的所有的操作,如果再在self.opQueue.isSuspended=no后马上打印队列的操作数可能队列的操作还是不为0 那是因为self.opQueue.isSuspended=no可能需要点点时间)
2.正在执行的操作也不会被取消
*/
/*取消所有操作*/
[self.opQueue cancelAllOperations]
依赖关系
NSBlockOperation * op1 = [NSBlockOperation blockOperationWithBlock:^{
[NSThread sleepForTimeInterval:1];
NSLog(@"1111");
}];
NSBlockOperation * op2 = [NSBlockOperation blockOperationWithBlock:^{
[NSThread sleepForTimeInterval:1];
NSLog(@"2222");
}];
NSBlockOperation * op3 = [NSBlockOperation blockOperationWithBlock:^{
[NSThread sleepForTimeInterval:2];
NSLog(@"3333");
}];
// op2 依赖 op1 op3 依赖op2 不要指定循环依赖,队列就不工作了,死了
[op2 addDependency:op1];
[op3 addDependency:op2];
//waitUntilFinished:是否等待 会卡住当前线程
[self.opQueue addOperations:@[op1,op2,op3] waitUntilFinished:YES];
NSLog(@"come here :%@",[NSThread currentThread]);
/*
1111
2222
3333
come here :<NSThread: 0x60c00006dd00>{number = 1, name = main}
*/
网友评论