一、NSOperation简介
相对于前面所说的NSThread,NSOperation同样用于多线程,但是相比较而言,NSOperation是更高级别的类,它大大的简化了处理多线程的过程,但是NSOperation是一个抽象基类,如果需要使用它的话,必须使用它的字累,或者自定义子类继承NSOperation,实现内部响应的方法。在此之前稍稍补充几个术语。
异步:不用阻塞当前线程来等待处理完成,而是允许后续操作,直至其它线程将处理完成,并回调通知此线程,不需要占用额外线程。
同步:对在一个系统中所发生的事件之间进行协调,在时间上出现一致性与统一化
线程 :是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源。
进程:是系统进行资源分配和调度的基本单位。
并行:一组程序按独立异步的速度执行。
并发:指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行。
二、使用NSOperation实现多线程的具体步骤
1) 先将需要执行的操作封装到一个NSOperation对象中;
2) 两种方式调用NSOperation;
2.1) NSOperation调用start方法执行任务,但默认是同步的;
2.2)将NSOperation对象添加到NSOperationQueue中,系统会自动异步执行NSOperation中的操作;
2.2.1)系统会自动将NSOperationQueue中的NSOperation取出来;
2.2.2)NSOperationQueue会开辟一条新线程,将取出的NSOperation封装的操作进行执行。
三、NSOperation的子类
1. NSInvocationOperation
2. NSBlockOperation
3. 自定义NSOperation子类
四、NSOperation相关操作
a.执行操作
NSOperation调用start方法即可开始执行操作,NSOperation对象默认按同步方式执行,也就是在调用start方法的那个线程中直接执行。NSOperation对象的isConcurrent方法会告诉我们这个操作相对于调用start方法的线程,是同步还是异步执行。isConcurrent方法默认返回NO,表示操作与调用线程同步执行。
[operation start];
b.取消操作[operation cancel];
c.监听执行操作operation.completionBlock = ^(){
NSLog(@"%s",__func__);
};
或[operation setCompletionBlock:^{
NSLog(@"%s",__func__);
}];
五、NSOperation子类的使用a.NSInvocationOperation
NSInvocationOperation是基于一个对象和selector来创建操作的。如果你已经有现有的方法来执行需要的任务,就可以使用这个类。
创建并执行的操作
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];
[operation start];
- (void)run
{
NSLog(@"---%@---",[NSThread currentThread]);
}
b.NSBlockOperation
NSBlockOperation能够并发地执行一个或多个block对象,所有相关的block都执行完之后,操作才算完成。
// 创建NSBlockOperation对象
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^(){
NSLog(@"线程1=====%@", [NSThread currentThread]);
}];
// 通过addExecutionBlock方法添加block操作
[operation addExecutionBlock:^{
NSLog(@"线程2=====%@",[NSThread currentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"线程3=====%@",[NSThread currentThread]);
}];
// 开始执行任务(这里还是同步执行)
[operation start];
c.自定义NSOperation子类
如果NSInvocationOperation和NSBlockOperation都不能够满足需求,那么就只能自定义继承于NSOperation的子类了,继承NSOperation需要重写NSOperation的基本方法。
例子:
.h文件
@interface PPDownLoadOperation : NSOperation
@property(nonatomic,copy)NSString *url;
@property(nonatomic,weak)id delegate;
@end
@protocol PPDownLoadOperationDelegate <NSObject>
- (void)didFishedDownLoadImage:(UIImage *)image;
@end
.m文件-(void)main
{
@autoreleasepool {
if (self.isCancelled) {
return;
}
NSURL *url = [NSURL URLWithString:self.url];
NSData *data = [NSData dataWithContentsOfURL:url];
if (self.isCancelled) {
url = nil;
data = nil;
return;
}
UIImage *imgae=[UIImage imageWithData:data];
if (self.isCancelled) {
imgae = nil;
return;
}
//图片下载完毕后,通知代理
if ([self.delegate respondsToSelector:@selector(didFishedDownLoadImage:)])
{
dispatch_async(dispatch_get_main_queue(), ^{//回到主线程,传递数据给代理对象
[self.delegate didFishedDownLoadImage:imgae];
});
}
}
}