美文网首页
iOS多线程-NSOperation简单介绍

iOS多线程-NSOperation简单介绍

作者: 学习天亦 | 来源:发表于2019-06-02 22:28 被阅读0次

    复习下线程的基础知识, 这里主要是参考文顶顶多线程篇复习写的。

    一、NSOperation简介

    1、NSOperation的作用

    配合使用NSOperation和NSOperationQueue也能实现多线程编程
    (1)先将需要执行的操作封装到一个NSOperation对象中
    (2)然后将NSOperation对象添加到NSOperationQueue中
    (3)系统会⾃动将NSOperationQueue中的NSOperation取出来
    (4)将取出的NSOperation封装的操作放到⼀条新线程中执⾏

    2、NSOperation的子类

    NSOperation是个抽象类,并不具备封装操作的能力,必须使⽤它的子类
    使用NSOperation⼦类的方式有3种:

    (1) NSInvocationOperation

    //创建NSInvocationOperation对象
    - (id)initWithTarget:(id)target selector:(SEL)sel object:(id)arg;
    
    //调用start方法开始执行操作, 一旦执行操作,就会调用target的sel方法
    - (void)start;
    

    注意
    默认情况下,调用了start方法后并不会开一条新线程去执行操作,而是在当前线程同步执行操作
    只有将NSOperation放到一个NSOperationQueue中,才会异步执行操作

    代码示例

    #import "ViewController.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        // 创建队列
        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        // 创建操作
        NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download) object:nil];
        // operation直接调用start,是同步执行(在当前线程执行操作)
    //    [operation start];
        // 添加操作到队列中,会自动异步执行
        [queue addOperation:operation];
    }
    
    - (void)download {
        NSLog(@"download-----%@", [NSThread currentThread]);
    }
    @end
    
    

    (2)NSBlockOperation

    创建NSBlockOperation对象

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

    通过addExecutionBlock:方法添加更多的操作

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

    注意:只要NSBlockOperation封装的操作数 > 1,就会异步执行操作

    代码示例

    #import "ViewController.h"
    @interface ViewController ()
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        //创建NSBlockOperation操作对象
        NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"NSBlockOperation------%@",[NSThread currentThread]);
        }];
        //开启执行操作 在主线程执行
        [operation start];
    }
    

    代码二

    #import "ViewController.h"
    @interface ViewController ()
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"---下载图片----1---%@", [NSThread currentThread]);
        }];
        
        [operation addExecutionBlock:^{
            NSLog(@"---下载图片----2---%@", [NSThread currentThread]);
        }];
        
        [operation addExecutionBlock:^{
            NSLog(@"---下载图片----3---%@", [NSThread currentThread]);
        }];
        // 任务数量 > 1,才会开始异步执行
        [operation start];
    }
    

    (3)自定义子类继承NSOperation,实现内部相应的⽅法

    • 重写- (void)main方法,在里面实现想执行的任务

    注意点
    自己创建自动释放池(因为如果是异步操作,无法访问主线程的自动释放池)
    经常通过- (BOOL)isCancelled方法检测操作是否被取消,对取消做出响应

    3、NSOperationQueue

    • NSOperationQueue的作用
      NSOperation可以调用start方法来执行任务,但默认是同步执行的
      如果将NSOperation添加到NSOperationQueue(操作队列)中,系统会自动异步执行NSOperation中的操作

    • 添加操作到NSOperationQueue中

    - (void)addOperation:(NSOperation *)op
    - (void)addOperationWithBlock:(void (^)(void))block;
    

    代码示例一:添加操作到主队列中,操作数大于0的才开启另外子线程执行

    #import "ViewController.h"
    @interface ViewController ()
    @end
    
    @implementation ViewController
    - (void)viewDidLoad {
        [super viewDidLoad];
        NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"---下载图片----11---%@", [NSThread currentThread]);
        }];
        
        [operation1 addExecutionBlock:^{
            NSLog(@"---下载图片----12---%@", [NSThread currentThread]);
        }];
        
        NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"---下载图片----2---%@", [NSThread currentThread]);
        }];
        
        NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"---下载图片----3---%@", [NSThread currentThread]);
        }];
     
        // 1、主队列
        NSOperationQueue *queue = [NSOperationQueue mainQueue];
        // 2.添加操作到主队列中 操作数大于0的才开启另外子线程执行
        [queue addOperation:operation1];
        [queue addOperation:operation2];
        [queue addOperation:operation3];
    }
    
    @end
    

    代码示例二:添加操作到NSOperationQueue中,自动异步执行

    #import "ViewController.h"
    @interface ViewController ()
    @end
    
    @implementation ViewController
    - (void)viewDidLoad {
        [super viewDidLoad];
        NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"---下载图片----11---%@", [NSThread currentThread]);
        }];
        
        [operation1 addExecutionBlock:^{
            NSLog(@"---下载图片----12---%@", [NSThread currentThread]);
        }];
        
        NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"---下载图片----2---%@", [NSThread currentThread]);
        }];
        
        NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"---下载图片----3---%@", [NSThread currentThread]);
        }];
        
        // 1.创建队列
        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        // 2.把操作添加到队列中 自动异步执行
        [queue addOperation:operation1];
        [queue addOperation:operation2];
        [queue addOperation:operation3];
    }
    @end
    

    注意:系统自动将NSOperationqueue中的NSOperation对象取出,将其封装的操作放到一条新的线程中执行。上面的代码示例中,一共有四个任务,operation1和operation2分别有一个任务,operation3有两个任务。一共四个任务,开启了四条线程。通过任务执行的时间可以看出,这些任务是并行执行的。
    提示:队列的取出是有顺序的,与打印结果并不矛盾。这就好比,选手A,BC虽然起跑的顺序是先A,后B,然后C,但是到达终点的顺序却不一定是A,B在前,C在后。

    相关文章

      网友评论

          本文标题:iOS多线程-NSOperation简单介绍

          本文链接:https://www.haomeiwen.com/subject/tqsstctx.html