多线程之NSOperation和NSOperationQueue

基本概念

1: NSOperation和NSOperationQueue的基本知识点:

    
 NSOperationQueue:代表一个 FIFO 的列队,它负责管理系统提交的多个 NSOperation,NSOperationQueue底层维护一个线性池,会按照顺序启动线程来执行提交给该列队的NSOperation任务.
 NSOperation:代表一个多线程任务.NSOperation有NSBlockOperation和NSInvocationOperation两个子类.NSOperation的使用方式有2种:1)自定义NSOperation,实现NSOperation子类.2)直接使用NSBlockOperation或者NSInvocationOperation.
 
2: 使用NSOperation,NSOperationQueue开发多线程非常简单,只需要2步:
 
  1):创建NSOperationQueue列队,并为该列队设置相应的属性.
  2):创建NSOperation子类的对象,并将该对象提交给NSOperationQueue列队,该列队将会按照顺序依次启动每个NSOperation.
 
3:NSOperationQueue的常用方法和属性
 
 //将NSOperation添加到NSOperationQueue中.
 - (void)addOperation:(NSOperation *)op;
 
 //将ops数组中的所有NSOperation添加到NSOperationQueue当中.如果第二个参数设置为 YES,将会阻塞当前线程,直到所有的NSOperation执行完成.如果为 NO, 该方法会立即返回,则ops数组中的所有NSOperation将以异步的方式执行,不会阻塞当前线程.
 - (void)addOperations:(NSArray<NSOperation *> *)ops waitUntilFinished:(BOOL)wait;
 
 //添加一个block形式的operation
 - (void)addOperationWithBlock:(void (^)(void))block;
 
 //只读属性,返回NSOperationQueue中所有的NSOperation
 @property (readonly, copy) NSArray<__kindof NSOperation *> *operations;
 
 //只读属性,返回NSOperationQueue中管理的NSOperation的数量.
 @property (readonly) NSUInteger operationCount ;
 
 //设置,获取列队最大的并发数量
 @property NSInteger maxConcurrentOperationCount;
 
 //是否暂停调度正在排队的NSOperation
 @property (getter=isSuspended) BOOL suspended;
 
 //NSOperationQueue的名字
 @property (nullable, copy) NSString *name ;
 
 NSOperation中新的qualityOfService的属性取代了原来的threadPriority。通过它可以推迟那些不重要的任务,从而让用户体验更加流畅。
 
 NSQualityOfService枚举定义了以下值:
 
 UserInteractive:和图形处理相关的任务,比如滚动和动画。
 UserInitiated:用户请求的任务,但是不需要精确到毫秒级。例如,如果用户请求打开电子邮件App来查看邮件。
 Utility:周期性的用户请求任务。比如,电子邮件App可能被设置成每五分钟自动检查新邮件。但是在系统资源极度匮乏的时候,将这个周期性的任务推迟几分钟也没有大碍。
 Background:后台任务,用户可能并不会察觉对这些任务。比如,电子邮件App对邮件进行引索以方便搜索。
 
 //服务质量
 @property NSQualityOfService qualityOfService NS_AVAILABLE(10_10, 8_0);
 
 @property (nullable, assign ) dispatch_queue_t underlyingQueue NS_AVAILABLE(10_10, 8_0);

 //取消所有NSOperationQueue列队中正在排队和执行的NSOperation.
- (void)cancelAllOperations;

 //阻塞当前线程,直到所有的NSOperation执行完成
- (void)waitUntilAllOperationsAreFinished;
 
//该方法返回执行当前的NSOperation的NSOperationQueue列队.
+ (nullable NSOperationQueue *)currentQueue ;
 
//该方法返回系统主线程的NSOperationQueue列队

+ (NSOperationQueue *)mainQueue ;


NSBlockOperation和NSInvocationOperation的使用

NSBlockOperation和NSInvocationOperation的使用非常相似,区别在于NSInvocationOperation用于将特定的方法封装成为NSOperation,而NSBlockOperation则用于将代码块封装成为NSOperation.

实例:NSBlockOperation和NSInvocationOperation下载图片

#import "ViewController.h"

@interface ViewController (){

    NSOperationQueue *queue;
}
@property (weak, nonatomic) IBOutlet UIImageView *imageView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self testOne];
}
-(void)testOne{
    
    queue=[[NSOperationQueue alloc]init];
    // 设置该队列最多支持10条并发线程
    queue.maxConcurrentOperationCount=10;
}
//使用IB创建界面,添加一个UIImageView和一个UIButton.这里使用NSInvocationOperation.
- (IBAction)downLoadImageButton:(UIButton *)sender {
    
    NSString* url = @"http://g.hiphotos.baidu.com/zhidao/pic/item/
                      37d3d539b6003af33c9aba42362ac65c1038b6eb.jpg";
    
    //以self的downloadImageFromURL:方法作为执行体,创建NSOperation
    NSInvocationOperation* operation = [[NSInvocationOperation alloc]
                                       initWithTarget:self selector:@selector(downloadImageFromURL:)
                                        object:url];
    //将NSOperation添加给NSOperationQueue
    [queue addOperation:operation];
    
}
// 定义一个方法作为线程执行体。
-(void)downloadImageFromURL:(NSString *) url
{
    // 从网络获取数据
    NSData *data = [[NSData alloc]
                    initWithContentsOfURL:[NSURL URLWithString:url]];
    // 将网络数据初始化为UIImage对象
    UIImage *image = [[UIImage alloc]initWithData:data];
    if(image != nil)
    {
        // 在主线程中执行updateUI:方法
        [self performSelectorOnMainThread:@selector(updateUI:)
                               withObject:image waitUntilDone:YES];
    }
    else
    {
        NSLog(@"---下载图片出现错误---");
    }
}
-(void)updateUI:(UIImage*) image
{
    self.imageView.image = image;
}

NSBlockOperation的使用,只要替换点击事件中的代码即可.
- (IBAction)downLoadImageButton:(UIButton *)sender {
    
    NSString* url = @"http://g.hiphotos.baidu.com/zhidao/pic/item/
                      37d3d539b6003af33c9aba42362ac65c1038b6eb.jpg";
    // 以传入的代码块作为执行体,创建NSOperation
    NSBlockOperation* operation = [NSBlockOperation blockOperationWithBlock:^{
         // 从网络获取数据
         NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]];
         // 将网络数据初始化为UIImage对象
         UIImage *image = [[UIImage alloc]initWithData:data];
         if(image != nil)
         {
          // 在主线程中执行updateUI:方法
             [self performSelectorOnMainThread:@selector(updateUI:)
                   withObject:image waitUntilDone:YES];
         }else
              {
               NSLog(@"---下载图片出现错误---");
              }
           }];
    // 将NSOperation添加给NSOperationQueue
    [queue addOperation:operation];
}

效果图:

           

自定义NSOperation的子类

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface SHOperation : NSOperation

@property (nonatomic , strong) NSURL* url;
@property (nonatomic , strong) UIImageView* imageView;

- (id)initWithURL:(NSURL*)url imageView:(UIImageView*)imageView;

@end

#import "SHOperation.h"

@implementation SHOperation

- (id)initWithURL:(NSURL*)url imageView:(UIImageView*)iv
{
    self = [super init];
    if (self) {
        _imageView = iv;
        _url = url;
    }
    return self;
}

//重写main方法,该方法将作为线程执行体也就是该线程需要完成的任务.
- (void)main
{
    //从网络获取数据,将网络数据初始化为UIImage对象
    NSData *data = [[NSData alloc]
                    initWithContentsOfURL:self.url];
    UIImage *image = [[UIImage alloc]initWithData:data];
    
    if(image != nil)
    {
        //因为 main方法代码将会在新线程中执行,所以需要在主线程中执行updateUI:方法
        [self performSelectorOnMainThread:@selector(updateUI:)
                               withObject:image waitUntilDone:YES]; // ①
    }
    else
    {
        NSLog(@"---下载图片出现错误---");
    }
}

-(void)updateUI:(UIImage*) image
{
    self.imageView.image = image;
}
@end

ViewController.m文件中

- (IBAction)downLoadImageButton:(UIButton *)sender {
    
    [self testTwo];
}

//NSOperation一般不会直接使用,而是创建子类,创建子类需要重写一个方法:-(void)main,该方法体将作为NSOperationQueue完成的任务.例子实现效果跟前面一样.
-(void)testTwo{

    queue=[[NSOperationQueue alloc]init];
    // 设置该队列最多支持10条并发线程
    queue.maxConcurrentOperationCount=10;
    
    // 定义要加载的图片的URL
    NSURL* url = [NSURL URLWithString:@"http://g.hiphotos.baidu.com/zhidao/pic/item/37d3d539b6003af33c9aba42362ac65c1038b6eb.jpg"];
    
    // 创建SHOperation对象.这里传入了需要的 url,以及下载成功后显示的imageView.
    SHOperation * operation = [[SHOperation alloc] initWithURL:url imageView:self.imageView];
    // 将NSOperation的子类的实例提交给NSOperationQueue
    [queue addOperation:operation];

}


推荐:

http://www.cnblogs.com/kenshincui/p/3983982.html#NSOperation

http://blog.leichunfeng.com/blog/2015/07/29/ios-concurrency-programming-operation-queues/




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值