NSOperation
概念
- NSOperation 是对GCD的封装
- queue、Operation
- NSOperation,NSOperationQueue,实现多线程并发
NSOperation 子类
NSOperation是抽象类,必须使用其子类。
三种方式:
- NSInvocationOperation
- NSBlockOperation
- 自定义子类,继承NSOperation,实现内部应用方法
NSInvocationOPeration
//1.invacationOperation
//注意:在默认情况下,调用start方法后,并不会开启一条新的线程去执行操作,而是在当前线程同步执行操作;只有将NSOperation放到NSOperationQueue中,才会异步执行操作
-(void)invocationOperation
{
NSInvocationOperation *ip = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(operation ) object:nil];
[ip start];
// [self performSelector:@selector(operation) withObject:nil];
}
NSInvocationOperation只有配合NSOperationQueue使用才能实现多线程编程
单独使用NSInvocationOperation不会开启线程,默认在当前线程(指执行该方法的线程)中同步指向
NSBlockOperation
和NSInvocationOperation相似,只是将方法替换成了Block,并可以使用addExecutionBlock追加任务
单独使用NSBlockOperation和NSInvocationOperation一样,默认在当前线程中同步执行
但是使用addExecutionBlock追加的任务是并发执行的,如果这个操作中的任务数量大于1,那么会开子线程并发执行任务,并且追加的任务不一定就是子线程,也有可能是主线程。所以上述中任务1、2、3执行是可期的,有序的,但是任务4、5、6是并发执行的,不可控的。
//2.blockOperation
//注意:只要NSBlockOperation封装的操作数大于1,就会开启新线程,异步执行
-(void)blockOperation
{
// 创建操作
NSBlockOperation *bp = [NSBlockOperation blockOperationWithBlock:^{
//在主线程中完成
NSLog(@"--1--%@",[NSThread currentThread]);
}];
//额外任务在子线程完成
[bp addExecutionBlock:^{
NSLog(@"--2--%@",[NSThread currentThread]);
}];
[bp start];
自定义子类,继承NSOperation
自定义一个继承自NSOperation的类RCOperation,在.m中重写main方法即可,main方法中就是要执行的操作.
- non concurrent operation 只需要重写一个 -main{}
- concurrent operation 需要实现 start,finished 两个method 和两个property asy,ex
// 自定义类
#import <Foundation/Foundation.h>
@interface PJXCustomOperation : NSOperation
@end
#import "PJXCustomOperation.h"
@implementation PJXCustomOperation
//在实现文件中实现-main方法
-(void)main
{
NSLog(@"--1--%@",[NSThread currentThread]);
}
@end
//调用
-(void)customOperation
{
PJXCustomOperation *cp = [[PJXCustomOperation alloc]init];
[cp start];
}
NSOperationQueue
NSOperation中的两种队列
- 主队列 通过mainQueue获得,凡是放到主队列中的任务都将在主线程执行,这点很重要!!!
- 非主队列 直接alloc init出来的队列。非主队列同时具备了并发和串行的功能,通过设置最大并发数属性来控制任务是并发执行还是串行执行
NSOperationQueue与GCD
GCD队列形式:1)全局 2)主队列 3)串行(自己创建的) 4)并行队列(自己创建)
NSOperationQueue队列形式:1)主队列 2)自己创建的非主队列
GCD:
串⾏类型:create & 主队列
并发类型:create & 全局并发队列
NSOperation:
主队列: [NSOperationQueue mainQueue] 和GCD中的主队列⼀样,串⾏队列
⾮主队列: [[NSOperationQueue alloc]init] ⾮常特殊(同时具备并发和串⾏的功能)
//默认情况下,⾮主队列是并发队列
NSOperationQueue *operationQueue = [[NSOperationQueue alloc ]init];
// invocationOperation
NSInvocationOperation *op = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(operation) object:nil];
[operationQueue addOperation:op];
创建的队列中的任务默认是异步执行的
// NSBlockOperation
// 创建操作
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
//在主线程中完成
NSLog(@"--1--%@",[NSThread currentThread]);
}];
//额外任务在子线程完成
[op2 addExecutionBlock:^{
NSLog(@"--2--%@",[NSThread currentThread]);
}];
[[operationQueue addOperation:op2];
//提供⼀个简便⽅法,使⽤Block直接添加任务
//1)创建操作,2)添加操作到队列中
[operationQueue addOperationWithBlock:^{
NSLog(@"--2--%@",[NSThread currentThread]);
}];
//自定义的Operation和NSOperationQueue组合:
-(void)operation{
NSOperationQueue *operationQueue = [[NSOperationQueue alloc ]init];
PJXCustomOperation *cp = [[PJXCustomOperation alloc]init];
[operationQueue addOperation:cp];
}
Queue的其他操作
- 设置最大并发数
设置最⼤并发数量 maxConcurrentOperationCount
/*
同⼀时间最多有多少个任务可以执⾏
串⾏执⾏任务!=只开⼀条线程 (线程同步)
maxConcurrentOperationCount >1 那么就是并发队列
maxConcurrentOperationCount == 1 那就是串⾏队列
maxConcurrentOperationCount == 0 不会执⾏任务
maxConcurrentOperationCount == -1 特殊意义 最⼤值 表示不受限制
*/
queue.maxConcurrentOperationCount = 1; - 暂停恢复和取消
setSupended
cancelAlloperation - 操作依赖
[opA addDependency:opB]; - 操作的监听
- (void (^)(void))completionBlock;
- (void)setCompletionBlock:(void (^)(void))block;
- 线程间通信
//2021/8/11 iOS中NSOperation详解 - 简书
//https://www.jianshu.com/p/cffd3ace0653 1/2
- (void)downloadImage{
__block UIImage *image1;
__block UIImage *image2;
//1.创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
//2.封装操作下载图⽚1
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSURL *url = [NSURL URLWithString:@"https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1H
NSData *data = [NSData dataWithContentsOfURL:url];
//拿到图⽚数据
image1 = [UIImage imageWithData:data];
}];
//3.封装操作下载图⽚2
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSURL *url = [NSURL URLWithString:@"https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1H
NSData *data = [NSData dataWithContentsOfURL:url];
//拿到图⽚数据
image2 = [UIImage imageWithData:data];
}];
//4.合成图⽚
NSBlockOperation *drawOp = [NSBlockOperation blockOperationWithBlock:^{
//4.1 开启图形上下⽂
UIGraphicsBeginImageContext(CGSizeMake(200, 200));
//4.2 画image1
[image1 drawInRect:CGRectMake(0, 0, 200, 100)];
//4.3 画image2
[image2 drawInRect:CGRectMake(0, 100, 200, 100)];
//4.4 根据图形上下⽂拿到图⽚数据
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
// NSLog(@"%@",image);
//4.5 关闭图形上下⽂
UIGraphicsEndImageContext();
//7.回到主线程刷新UI
[[NSOperationQueue mainQueue]addOperationWithBlock:^{
self.imageView.image = image;
NSLog(@"刷新UI---%@",[NSThread currentThread]);
}];
}];
//5.设置操作依赖
[drawOp addDependency:op1];
[drawOp addDependency:op2];
//6.添加操作到队列中执⾏
[queue addOperation:op1];
[queue addOperation:op2];
[queue addOperation:drawOp];
}
浙公网安备 33010602011771号