iOS:操作队列实现多线程NSOperation

NSOperation具体使用:直接继承NSObject

它的子类有:NSBlockOperation、NSInvocationOperation

还有一个必须的类,队列,用来装创建的线程 NSOperationQueue

理解:这个方式是如何实现多线程呢?是通过操作队列来实现多线程的。即主线程是一个主队列,再创建一个队列并将其他的线程加入其中同步执行。如果对共享资源的争夺放在主线程队列中,则不需要关心线程管理,数据同步的事情,可以把精力放在自己需要执行的操作上;否则的话,仍需要关心数据同步的问题。

说明:

一般用子类创建Operation实例来实现多线程,NSBlockOperation、NSInvocationOperation这两种方式均可以使用,前一个采用的是将线程的执行过程封装为block函数,第二个采用的是将线程的执行过程封装为方法。

1、NSOperation的详解:

队列优先级枚举:

typedef NS_ENUM(NSInteger, NSOperationQueuePriority) {

NSOperationQueuePriorityVeryLow = -8L,

NSOperationQueuePriorityLow = -4L,

NSOperationQueuePriorityNormal = 0,

NSOperationQueuePriorityHigh = 4,

NSOperationQueuePriorityVeryHigh = 8

};

属性:

@property (readonly, getter=isCancelled) BOOL cancelled;               //线程是否取消

@property (readonly, getter=isExecuting) BOOL executing;              //线程是否在执行

@property (readonly, getter=isFinished) BOOL finished;                  //线程是否执行完毕

@property (readonly, getter=isConcurrent) BOOL concurrent;          //线程是否并发执行

@property (readonly, getter=isAsynchronous) BOOL asynchronous; //是否线程异步,已经被线程同步覆盖

@property (readonly, getter=isReady) BOOL ready;                       //线程是否处于就绪状态

@property (readonly, copy) NSArray *dependencies;                      //线程依赖的数组

@property NSOperationQueuePriority queuePriority;                  //队列优先级

@property (copy) void (^completionBlock)(void);                           //block函数

@property double threadPriority;                                             //线程优先级

@property NSQualityOfService qualityOfService;                        //服务质量

@property (copy) NSString *name;                                           //线程名字

方法:

- (void)start;   //启动线程

- (void)main;   //主线程

- (void)cancel;//取消线程

- (void)addDependency:(NSOperation *)op; //添加线程依赖(只有上一个线程一直执行,依赖的下一个线程才开始执行)

- (void)removeDependency:(NSOperation *)op; //移除线程依赖

- (void)waitUntilFinished  //等待抢占资源的线程结束

================================================================================

2、NSIndivocationOperation的详解:NSInvocationOperation : NSOperation

属性:

@property (readonly, retain) NSInvocation *invocation;    //线程的调用

@property (readonly, retain) id result;

方法:

//创建线程的实例方法,可以添加线程事件

- (instancetype)initWithTarget:(id)target selector:(SEL)sel object:(id)arg;

//创建线程的实例方法

- (instancetype)initWithInvocation:(NSInvocation *)inv ;

=================================================================

3、NSBlockOperation的详解:NSBlockOperation : NSOperation

属性:@property (readonly, copy) NSArray *executionBlocks;   //执行block的线程队列数组

方法:

※创建线程的类方法,执行block函数

+ (instancetype)blockOperationWithBlock:(void (^)(void))block;

※添加执行线程对列block函数

- (void)addExecutionBlock:(void (^)(void))block;

==========================================================

4、NSOperationQueue队列的详解:NSOperationQueue : NSOperation

属性:

@property (readonly, copy) NSArray *operations;           //操作线程数组

@property (readonly) NSUInteger operationCount           //一次能执行的线程数量

@property NSInteger maxConcurrentOperationCount;     // 能并发执行的最大线程数量

@property (getter=isSuspended) BOOL suspended;                  //是否暂时线程

@property (copy) NSString *name ;                                      //线程名字

@property NSQualityOfService qualityOfService;                     //服务质量

@property (assign /* actually retain */) dispatch_queue_t underlyingQueue;

方法:

※添加线程

- (void)addOperation:(NSOperation *)op;

※等待添加线程数组

- (void)addOperations:(NSArray *)ops waitUntilFinished:(BOOL)wait;

※添加线程并执行block函数的实例方法

- (void)addOperationWithBlock:(void (^)(void))block;

※取消所有的线程

- (void)cancelAllOperations;

※等待所有的线程执行完毕

- (void)waitUntilAllOperationsAreFinished;

※当前队列

+ (NSOperationQueue *)currentQueue;

※主队列

+ (NSOperationQueue *)mainQueue;

具体举例如下:多线程卖票(将当前票数和线程名字显示在文本视图中)

方法一:采用NSOpeartion的子类NSIndivocationOperation创建多线程:

1.文本视图控件并关联以及声明票属性

@interface ViewController ()
{
    int tickets;
}
@property (weak, nonatomic) IBOutlet UITextView *textView;

2.设置票数和文本视图

    //准备数据
    tickets = 20;

    //设置textView
    self.textView.text = @"";
    self.textView.layoutManager.allowsNonContiguousLayout = NO;

3.创建NSOperation实例(线程)

//创建NSOperation并加到队列
    NSInvocationOperation *operation1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(operationSellMethod:) object:@"售票线程-1"];
     NSInvocationOperation *operation2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(operationSellMethod:) object:@"售票线程-2"];

4.将operation加入创建的队列中

    //创建队列
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];

    //为操作之间添加依赖,只有被依赖的线程执行完,依赖的线程才能执行
    //[operation1 addDependency:operation2];

    //将opearion放入队列
    [queue addOperation:operation1];
    [queue addOperation:operation2];

5.更新UI的主线程队列

#pragma mark -更新UI
-(void)appendTextView:(NSString *)text
{
    //1.获取原来的内容
    NSMutableString *content = [[NSMutableString alloc]initWithString:self.textView.text];
    NSRange range = NSMakeRange(content.length, 1);

    //2.追加新的内容
    [content appendString:[NSString stringWithFormat:@"\n%@",text]];
    [self.textView setText:content];

    //3.滚动视图
    [self.textView scrollRangeToVisible:range];
}

6.执行对共享抢占资源操作的过程

#pragma mark -执行线程过程

-(void)operationSellMethod:(NSString*)name
{
    while (YES)
    {
        //1.判断是否有票
        if (tickets>0)
        {
            //没有将共享抢占资源放到主队列中,仍然要关心数据同步的问题
         @synchronized(self)
            {
                NSString *info = [NSString stringWithFormat:@"总的票数:%d,当前的线程:%@",tickets,name];

                [[NSOperationQueue mainQueue]addOperationWithBlock:^{
                    [self appendTextView:info];
                }];

                //2.卖票
                tickets--;
            }

            //3.线程休眠
            if([name isEqualToString:@"售票线程-1"])
            {
                [NSThread sleepForTimeInterval:0.3f];
            }
            else
            {
                [NSThread sleepForTimeInterval:0.2f];
            }
        }
        else
        {
            //更新UI
            NSString *info = [NSString stringWithFormat:@"票已经售完,当前的线程:%@",name];
            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                [self appendTextView:info];
            }];

            //退出线程
            break;
        }
    }
}

方法二:采用NSOpeartion的子类NSBlockOperation创建多线程:

1.文本视图控件并关联以及声明票属性

@interface ViewController ()
{
    int tickets;
}
@property (weak, nonatomic) IBOutlet UITextView *textView;

2.设置票数和文本视图

    //准备数据
    tickets = 20;

    //设置textView
    self.textView.text = @"";
    self.textView.layoutManager.allowsNonContiguousLayout = NO;

3.创建队列和操作block线程

    //创建队列
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];

    //设置并行的线程数量
    //[queue setMaxConcurrentOperationCount:2];

    //在队列中添加block的operation
    [queue addOperationWithBlock:^{
        [self operationSellMethod:@"售票线程-1"];
    }];

    [queue addOperationWithBlock:^{
        [self operationSellMethod:@"售票线程-2"];
    }];

    NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
        [self operationSellMethod:@"售票线程-3"];
    }];
    [queue addOperation:blockOperation];

4.更新UI的主线程队列

#pragma mark -更新UI
-(void)appendTextView:(NSString *)text
{
    //1.获取原来的内容
    NSMutableString *content = [[NSMutableString alloc]initWithString:self.textView.text];
    NSRange range = NSMakeRange(content.length, 1);

    //2.追加新的内容
    [content appendString:[NSString stringWithFormat:@"\n%@",text]];
    [self.textView setText:content];

    //3.滚动视图
    [self.textView scrollRangeToVisible:range];
}

5.执行对共享抢占资源操作的过程

#pragma mark -执行线程过程

#pragma mark -执行线程过程
-(void)operationSellMethod:(NSString*)name
{
    while (YES)
    {
        //1.判断是否有票
        if (tickets>0)
        {
            //将共享抢占资源放入主队列,不需要再关心数据同步的问题
            [[NSOperationQueue mainQueue]addOperationWithBlock:^{

                NSString *info = [NSString stringWithFormat:@"总的票数:%d,当前的线程:%@",tickets,name];

                [self appendTextView:info];

                //2.卖票
                tickets--;
            }];

            //3.线程休眠
            if([name isEqualToString:@"售票线程-1"])
            {
                [NSThread sleepForTimeInterval:0.3f];
            }
            else
            {
                [NSThread sleepForTimeInterval:0.2f];
            }
        }
        else
        {
            //更新UI
            NSString *info = [NSString stringWithFormat:@"票已经售完,当前的线程:%@",name];
            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                [self appendTextView:info];
            }];

            //退出线程
            break;
        }
    }
}

演示结果如下:

时间: 2024-10-10 17:59:49

iOS:操作队列实现多线程NSOperation的相关文章

多线程NSOperation使用方法

/*------------------------------  NSOperation使用   -----------------------------------*/ 重点:操作 NSOperation 和操作队列 NSOperationQueue! { 1.NSOperation(操作)简介: NSOperation: // 本质是对 GCD 的封装, OC 语言. NSOperation 和 GCD 的比较: GCD使用场合: 一些简单的需求,简单的多线程操作. //简单高效 NSO

iOS边练边学--多线程NSOperation介绍,子类实现多线程的介绍(任务和队列),队列的取消、暂停(挂起)和恢复,操作依赖与线程间的通信

一.NSOperation NSOperation和NSOperationQueue实现多线程的具体步骤 先将需要执行的操作封装到一个NSOperation对象中 然后将NSOperation对象添加到NSOperationQueue中 系统会自动将NSOperationQueue中的NSOperation取出来 将取出的NSOperation封装的操作放到一条新线程中执行 NSOperation是个抽象类,并不具备封装操作的能力,必须使用它的子类 使用NSOperation子类的方式有3种 N

ios多线程操作(十一)—— NSOperation的高级操作

NSOperation可以调用start方法来执行任务,但默认是同步执行的,如果将NSOperation添加到      NSOperationQueue(操作队列)中,系统会自动异步执行队列中的操作. NSOperationQueue中可以对操作进行取消,暂停和恢复 取消函数为: [objc] view plain copy - (void)cancelAllOperations; 也可以调用NSOperation的cancel方法来取消单个操作 [objc] view plain copy

iOS的三种多线程技术NSThread/NSOperation/GCD

1.iOS的三种多线程技术 1.NSThread 每个NSThread对象对应一个线程,量级较轻(真正的多线程) 2.以下两点是苹果专门开发的"并发"技术,使得程序员可以不再去关心线程的具体使用问题 NSOperation/NSOperationQueue 面向对象的线程技术 GCD -- Grand Central Dispatch(派发) 是基于C语言的框架,可以充分利用多核,是苹果推荐使用的多线程技术. 以上这三种编程方式从上到下,抽象度层次是从低到高的,抽象度越高的使用越简单,

iOS中的多线程 NSOperation

在ios中,使用多线程有三种方式,分别是:NSThread.NSOperation和NSOperationQueue.GCD,在本节,主要讲解一下NSOperation的使用. NSOperation和NSOperationQueue这种方式实际上是将NSOperation的对象放到一个NSOperationQueue队列中,然后依次启动操作,类似于线程池的使用. 在使用的过程中,NSOperation的操作使用的是它的子类,分别是NSInvocationOperation和NSBlockOpe

iOS之多线程NSOperation

目前在 iOS 和 OS X 中有两套先进的同步 API 可供我们使用:NSOperation 和 GCD .其中 GCD 是基于 C 的底层的 API ,而 NSOperation 则是 GCD 实现的 Objective-C API. 1. 什么时候使用NSOperationQueue而不是GCD 比如你可能写过类似这样的代码(这样来请求网络数据): 1 dispatch_async(_Queue, ^{ 2 3 //请求数据 4 NSData *data = [NSData dataWit

【iOS】多线程NSOperation

NSOperation是苹果封装的一套多线程的东西,不像GCD是纯C语言的,这个是OC的.但相比较之下GCD会更快一些,但本质上NSOPeration是多GDC的封装. 一.NSOperation与GCD的比较 GCD是基于c的底层api,NSOperation属于object-c类.ios首先引入的是NSOperation,IOS4之后引入了GCD和NSOperationQueue并且其内部是用gcd实现的. GCD优点:GCD主要与block结合使用.代码简洁高效.执行效率稍微高点. NSO

iOS开发——多线程OC篇&(九)多线程NSOperation介绍

NSOperation介绍 一.NSOperation简介 1.简单说明 NSOperation的作?:配合使用NSOperation和NSOperationQueue也能实现多线程编程 NSOperation和NSOperationQueue实现多线程的具体步骤: (1)先将需要执行的操作封装到一个NSOperation对象中 (2)然后将NSOperation对象添加到NSOperationQueue中 (3)系统会?动将NSOperationQueue中的NSOperation取出来 (4

iOS多线程---NSOperation介绍和使用

1.  NSOperation实现多线程编程,需要和NSOperationQueue一起使用. (1)先将要执行的操作封装到NSOperation中 (2)将NSOperation对象添加到NSOperationQueue中 (3)系统将自动将NSOPeration从NSOperationQueue中取出来,放到一个新的线程中去执行 2.NSOperation 的子类 NSOperation是一个抽象类,并没有封装操作的能力.因此要用到它的子类: (1)NSInvocationOperation