zoukankan      html  css  js  c++  java
  • iOS-----使用NSOperation与NSOperationQueue实现多线程

    使用NSOperation与NSOperationQueue实现多线程

    NSOperation与NSOperationQueue的基本理论如下。

    NSOperationQueue

    代表一个FIFO的队列,它负责管理系统提交的多个NSOperation,NSOperationQueue底层维护一个线程池,会按顺序启动线程来执行提交给该队列的NSOperation任务

    NSOperation

    代表一个多线程任务。NSOperation还有NSInvocationOperation、NSBlockOperation两个子类。NSOperation有两种使用方式:①开发者实现NSOperation的子类;②开发者直接使用NSInvocationOperation或NSBlockOperation子类。

    使用NSOperation、NSOperationQueue开发多线程非常简单,只要如下两步

    1

    创建NSOperationQueue队列,并为该队列设置相关属性。

    2

    创建NSOperation子类的对象,并将该对象提交给NSOperationQueue队列,该队列将会按顺序依次启用每个NSOperation。

    NSOperationQueue负责管理、执行所有的NSOperation,它底层维护着一个线程池,开发者提交的NSOperation正是由该线程池中的线程负责执行的。NSOperationQueue提供了如下常用方法。

     
     
         

    使用NSInvocationOperation和NSBlockOperation

        NSInvocationOperation和NSBlockOperation都是NSOperation的子类,都可在程序中直接使用,用于封装需要异步执行的任务。

       NSInvocationOperation和NSBlockOperation在用法上非常相似,区别是NSInvocationOperation用于将特定对象的特定方法封装成NSOperation,而NSBlockOperation则用于将代码封装成NSOperation。

    创建NSInvocationOperation的代码片段如下:

     

    创建NSBlockOperation的代码片段如下:

     

    一旦得到NSOperation对象之后,将NSOperation对象提交给NSOperationQueue即可。

    实例:使用NSBlockOperation下载图片

    下面是该实例的视图控制器类的实现部分代码。

     1 @implementation ViewController
     2 
     3 NSOperationQueue* queue;
     4 
     5 - (void)viewDidLoad
     6 
     7 {
     8 
     9    [super viewDidLoad];
    10 
    11    queue = [[NSOperationQueue alloc] init];
    12 
    13    // 设置该队列最大支持10个并发线程
    14 
    15    queue.maxConcurrentOperationCount = 10;
    16 
    17 }
    18 
    19 - (IBAction)clicked:(id)sender
    20 
    21 {
    22 
    23   NSString* url = @” http://pic14.nipic.com/20110522/7411759_164157418126_2.jpg”;
    24 
    25   // 以传入的代码块作为执行体,创建NSOperation
    26 
    27   NSBlockOperation* operation = [NSBlockOperation blockOperationWithBlock:^{
    28 
    29    // 从网络获取数据
    30 
    31    NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]];
    32 
    33   // 将网络数据初始化为UIImage对象
    34 
    35   UIImage *image = [[UIImage alloc] initWithData: data];
    36 
    37   if(image != nil)
    38 
    39 {
    40 
    41   // 在主线程中执行updateUI:方法
    42 
    43  [self performSelectorOnMainThread:@selector(updateUI:)
    44 
    45 withObject:image waithUntilDone:YES];//
    46 
    47 }
    48 
    49 else
    50 
    51 {
    52 
    53   NSLog(@”---下载图片出现错误---”);
    54 
    55 }
    56 
    57 }];
    58 
    59 // 将NSOperation添加给NSOperationQueue
    60 
    61 [queue addOperation:operation];
    62 
    63 }
    64 
    65 - (void)updateUI:(UIImage*)image
    66 
    67 {
    68 
    69   self.iv.image = image;
    70 
    71 }
    72 
    73 @end

    该程序创建了一个NSBlockOperation对象,接下来将该对象提交给NSOperationQueue即可.由于该代码块将会在线程中执行,因此程序在①号代码处调用了performSelectorOnMainThread:withObject: waitUntilDone:方法在主线程中更新iv控件显示的图片.

    定义NSOperation子类

    NSOperation一般不会直接拿来使用,而是选择创建它的子类,创建NSOperation的子类需要重写一个方法:- (void)main,该方法的方法将作为NSOperationQueue完成的任务。

    下面程序示范了使用NSOperation的子类来下载网络图片。该示例的界面与前面介绍的使用NSThread下载图片的界面基本相似,只是该程序将会使用NSOperation的子类来启动多线程执行下载。该示例的界面上同样只有一个UIImageView和一个UIButton,程序为UIButton的“Touch Up Inside”时间绑定clicked:事件处理方法。

    下面是LCDownImageOperation类的接口部分代码。

     1 LCDownLoadImageOperation.h文件
     2 
     3 #import<Foundation/Foundation.h>
     4 
     5 // 定义NSOperation的子类
     6 
     7 @interface LCDownImageOperation:NSOperation
     8 
     9 @property (nonatomic, strong)NSURL*  url;
    10 
    11 @property (nonatomic, weak)UIImageView* imageView;
    12 
    13 - (id)initWithURL:(NSURL*)url imageView:(UIImageView*)iv;
    14 
    15 @end
    16 
    17 LCDownLoadImageOperation.m文件
    18 
    19 @implementation LCDownLoadImageOperation
    20 
    21 - (id)initWithURL:(NSURL*)url imageView:(UIImageView*)iv
    22 
    23 {
    24 
    25    self = [super init];
    26 
    27    if(self)
    28 
    29    {
    30 
    31      _imageView = iv;
    32 
    33      _url = url;
    34 
    35 }
    36 
    37 return self;
    38 
    39 }
    40 
    41 // 重写main方法,该方法将作为线程执行体
    42 
    43 - (void)main
    44 
    45 {
    46 
    47   // 从网络获取数据
    48 
    49   NSData *data = [[NSData alloc] initWithContentsOfURL:self.url];
    50 
    51   // 将网络数据初始化为UIImage对象
    52 
    53   UIImage *image = [[UIImage alloc] initWithData;data];
    54 
    55   if(image !=nil)
    56 
    57   {
    58 
    59      // 在主线程中执行updateUI:方法
    60 
    61      [self performSelectorOnMainThread:@selector(updateUI:)
    62 
    63 withObject:image waitUntilDone:YES];//
    64 
    65 }
    66 
    67  else
    68 
    69 {
    70 
    71    NSLog(@”+++下载图片出现错误+++”);
    72 
    73 }
    74 
    75 }
    76 
    77 - (void)updateUI:(UIImage*)image
    78 
    79 {
    80 
    81    self.imageView.image = image;
    82 
    83 }
    84 
    85 @end

    说明

       上面的代码创建了NSOperation类的子类,并重写了main方法,该方法将会作为该NSOperation所启动线程的执行体----也就是代表该线程要完成的任务.由于main方法的代码将会在新线程中执行,因此程序同样调用了performSelectorOnMainThread:withObject:waitUntilDone:方法在主线程中更新iv控件显示的图片.

    代码片段

       创建了该NSOperation的子类之后,接下来只要创建该子类的实例,并将它提交给NSOperationQueue即可.视图控制器类的实现部分使用了LCDownImageOperation从网络下载图片.下面是视图控制器类的实现部分代码.

     1  ViewController.m
     2 
     3 @implementation ViewController
     4 
     5 NSOperationQueue *queue;
     6 
     7 - (void)viewDidLoad
     8 
     9 {
    10 
    11    [super viewDidLoad];
    12 
    13    queue = [[NSOperationQueue alloc] init];
    14 
    15    // 设置该队列最大支持10个并发线程
    16 
    17    queue.maxConcurrentOperationCount = 10;
    18 
    19 }
    20 
    21 - (IBAction)clicked:(id)sender
    22 
    23 {
    24 
    25 // 定义要加载的图片的URL
    26 
    27 NSURL *url = [NSURL URLWithString:@” http://img2.imgtn.bdimg.com/it/u=194240101,2532182839&fm=21&gp=0.j      pg”];
    28 
    29 // 创建LCDownImageOperation对象
    30 
    31 LCDownImageOperation* operation = [[LCDownImageOperation alloc] initWithURL:url imageView:self.iv];
    32 
    33 // 将NSOperation的子类的实例提交给NSOperationQueue
    34 
    35 [queue addOperation:operation];
    36 
    37 }
    38 
    39 @end

    说明

        上面程序中的代码就是使用LCDownImageOperation实现多线程下载的关键代码,只要创建LCDownImageOperation实例,然后将该实例提交给NSOperationQueue即可.

    小结

          iOS提供了3种多线程支持:①使用NSThread开发多线程应用;②使用GCD实现多线程;③使用NSOperation和NSOperationQueue实现多线程.

  • 相关阅读:
    [苹果maccms] MACCMS苹果cms宝塔定时任务添加教程说明
    [苹果cmsV10]新版本演员库分类报无权限问题和解决方法!
    CentOS 6.8安装Python2.7.13
    [HOWTO] Install Sphinx for A Script Pro
    A Script Pro nginx URL重写规则无法播放MP4解决方法
    随机跳转
    UI库
    vuex
    vue 数据请求
    vue守卫、储存与路由模式
  • 原文地址:https://www.cnblogs.com/congli0220/p/5021625.html
Copyright © 2011-2022 走看看