一、NSOperation简介
1、简单说明
- NSOperation的作⽤:配合使用NSOperation和NSOperationQueue也能实现多线程编程
- NSOperation和NSOperationQueue实现多线程的具体步骤:
(1)先将需要执行的操作封装到一个NSOperation对象中
(2)然后将NSOperation对象添加到NSOperationQueue中
(3)系统会⾃动将NSOperationQueue中的NSOperation取出来
(4)将取出的NSOperation封装的操作放到⼀条新线程中执⾏
2、NSOperation的子类
- NSOperation是个抽象类,并不具备封装操作的能力,必须使⽤它的子类
- 使用NSOperation⼦类的方式有3种:
(1)NSInvocationOperation
(2)NSBlockOperation
(3)自定义子类继承NSOperation,实现内部相应的⽅法
3、执行
执行一个operation有两种方:
- 第一种是自己手动的调用start这个方法,这种方法调用会在当前调用的线程进行同步执行,所以在主线程里面自己一定要小心的调用,不然就会把主线程给卡死,还不如直接用GCD呢。
- 第二种是将operation添加到operationQueue中去,这个也是我们用得最多的也是提倡的方法。NSOperationQueue会在我们添加进去operation的时候尽快进行执行。当然如果NSOperationQueue的maxConcurrentOperationCount如果设置为1的话,进相当于FIFO了。
二、 操作
1、NSInvocationOperation子类
注意:操作对象默认在主线程中执行,只有添加到队列中才会开启新的线程。即默认情况下,如果操作没有放到队列中queue中,都是同步执行。只有将NSOperation放到一个NSOperationQueue中,才会异步执行操作
1.1 创建并执行操作
NSInvocationOperation *operation=[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];
[operation start];//开始执行任务(同步执行)
1.2 事件响应
- (void)run {
NSLog(@"%@",[NSThread currentThread]);
}
1.3 执行结果
**2016-07-06 10:15:32.593 ****类库****[6716:2832599] <NSThread: 0x166456b0>{number = 1, name = main}**
2、NSBlockOperation子类
2.1 创建并执行操作
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^(){
NSLog(@"执行了一个新的操作,线程:%@", [NSThread currentThread]);
}];
// 开始执行任务(这里还是同步执行)
[operation start];
2.2.通过addExecutionBlock方法添加block操作
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^(){
NSLog(@"执行第1次操作,线程:%@", [NSThread currentThread]);
}];
[operation addExecutionBlock:^() {
NSLog(@"又执行了1个新的操作,线程:%@", [NSThread currentThread]);
}];
[operation addExecutionBlock:^() {
NSLog(@"又执行了1个新的操作,线程:%@", [NSThread currentThread]);
}];
[operation addExecutionBlock:^() {
NSLog(@"又执行了1个新的操作,线程:%@", [NSThread currentThread]);
}];
// 开始执行任务
[operation start];
结果
**2016-07-06 10:28:12.476 ****类库****[6730:2835101] 2****又执行了****1****个新的操作,线程:****<NSThread: 0x17d3ca10>{number = 2, name = (null)}**
**2016-07-06 10:28:12.476 ****类库****[6730:2835035] 1****执行第****1****次操作,线程:****<NSThread: 0x17d19150>{number = 1, name = main}**
**2016-07-06 10:28:12.477 ****类库****[6730:2835101] 3****又执行了****1****个新的操作,线程:****<NSThread: 0x17d3ca10>{number = 2, name = (null)}**
**2016-07-06 10:28:12.477 ****类库****[6730:2835035] 4****又执行了****1****个新的操作,线程:****<NSThread: 0x17d19150>{number = 1, name = main}**
可以看出,这4个block是并发执行的,也就是在不同线程中执行的
3、NSOperationQueue
NSOperationQueue的作⽤:
(1) NSOperation可以调⽤start⽅法来执⾏任务,但默认是同步执行的
(2) 如果将NSOperation添加到NSOperationQueue(操作队列)中,系统会自动异步执行NSOperation中的操作
(3) 添加操作到NSOperationQueue中,自动执行操作,自动开启线程
3.1 创建队列
NSOperationQueue * queue = [[NSOperationQueue alloc] init];
3.2 将操作添加到队列当中
//第一种方式
[queue addOperation:operation1];
//第二种方式
[queue addOperationWithBlock:^{
NSLog(@"NSBlockOperation%@",[NSThread currentThread]);
}];
3.3 示例
NSOperationQueue * queue = [[NSOperationQueue alloc] init];
NSInvocationOperation *operation1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^(){
NSLog(@"2:NSBlockOperation:%@", [NSThread currentThread]);
}];
[operation2 addExecutionBlock:^() {
NSLog(@"3:NSBlockOperation:%@", [NSThread currentThread]);
}];
[operation2 addExecutionBlock:^() {
NSLog(@"4:NSBlockOperation:%@", [NSThread currentThread]);
}];
[operation2 addExecutionBlock:^() {
NSLog(@"5:NSBlockOperation:%@", [NSThread currentThread]);
}];
[queue addOperation:operation1];
[queue addOperation:operation2];
- (void)run {
NSLog(@"1:NSInvocationOperation:%@", [NSThread currentThread]);
}
结果:
**2016-07-06 11:03:15.197 ****类库****[6736:2840181] 1:NSInvocationOperation****:****<NSThread: 0x16542de0>{number = 2, name = (null)}**
**2016-07-06 11:03:15.198 ****类库****[6736:2840176] 2:NSBlockOperation****:****<NSThread: 0x16521a80>{number = 3, name = (null)}**
**2016-07-06 11:03:15.198 ****类库****[6736:2840176] 3:NSBlockOperation****:****<NSThread: 0x16521a80>{number = 3, name = (null)}**
**2016-07-06 11:03:15.198 ****类库****[6736:2840176] 4:NSBlockOperation****:****<NSThread: 0x16521a80>{number = 3, name = (null)}**
**2016-07-06 11:03:15.200 ****类库****[6736:2840176] 5:NSBlockOperation****:****<NSThread: 0x16521a80>{number = 3, name = (null)}**
可以看出任务是异步并发执行的