• ios开发多线程二:NSOperationQueue的基本使用


    #import "ViewController.h"
    #import "XMGOperation.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    #pragma mark ----------------------
    #pragma mark Events
    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        [self customWithQueue];
    }
    
    #pragma mark ----------------------
    #pragma mark Methods
    
    -(void)invocationOperationWithQueue
    {
        //1.创建操作,封装任务
        /*
         第一个参数:目标对象 self
         第二个参数:调用方法的名称
         第三个参数:前面方法需要接受的参数 nil
         */
        NSInvocationOperation *op1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download1) object:nil];
        NSInvocationOperation *op2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download2) object:nil];
        NSInvocationOperation *op3 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download3) object:nil];
        
        //2.创建队列
        /*
         GCD:
         串行类型:create & 主队列
         并发类型:create & 全局并发队列
         NSOperation:1:本身不能进行封装任务,必须依靠其子类,NSInvocationOperation,NSBlockOperation或是自定义类,重写main方法来封装任务。这三个子类若没有指定队列,则默认任务是在当前队列中执行的
         主队列:   [NSOperationQueue mainQueue] 和GCD中的主队列一样,串行队列
         非主队列: [[NSOperationQueue alloc]init]  非常特殊(同时具备并发和串行的功能)
         //默认情况下,非主队列是并发队列:可通过设置最大并发数:为0:没有队列执行操作,1:主队列 大于1,并发队列     */
        NSOperationQueue *queue = [[NSOperationQueue alloc]init];
        
        //3.添加操作到队列中
        [queue addOperation:op1];   //内部已经调用了[op1 start]
        [queue addOperation:op2];
        [queue addOperation:op3];
    }
    
    -(void)blockOperationWithQueue
    {
        //1.创建操作
        NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"1----%@",[NSThread currentThread]);
           
        }];
        
        NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"2----%@",[NSThread currentThread]);
        }];
        
        NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"3----%@",[NSThread currentThread]);
        }];
        
        //追加任务:当某个操作的任务数量大于1时,默认会开启子线程并发执行,有可能是子线程有可能是主线程不确定
        [op2 addExecutionBlock:^{
            NSLog(@"4----%@",[NSThread currentThread]);
        }];
        
        [op2 addExecutionBlock:^{
            NSLog(@"5----%@",[NSThread currentThread]);
        }];
        
        [op2 addExecutionBlock:^{
            NSLog(@"6----%@",[NSThread currentThread]);
        }];
        
        //2.创建队列
        NSOperationQueue *queue = [[NSOperationQueue alloc]init];
        
        //3.添加操作到队列
        [queue addOperation:op1];
        [queue addOperation:op2];
        [queue addOperation:op3];
        
        //简便方法:addOperationWithBlock:直接封装任务添加到队列中
        //1)创建操作,2)添加操作到队列中
        [queue addOperationWithBlock:^{
            NSLog(@"7----%@",[NSThread currentThread]);
        }];
        
    }
    
    -(void)customWithQueue
    {
        //1.封装操作
        XMGOperation *op1 = [[XMGOperation alloc]init];
        XMGOperation *op2 = [[XMGOperation alloc]init];
        
        //2.创建队列
        NSOperationQueue *queue = [[NSOperationQueue alloc]init];
        
        //3.添加操作到队列
        [queue addOperation:op1];
        [queue addOperation:op2];
        
    }
    
    
    -(void)download1
    {
        NSLog(@"%s----%@",__func__,[NSThread currentThread]);
    }
    
    -(void)download2
    {
        NSLog(@"%s----%@",__func__,[NSThread currentThread]);
    }
    
    
    -(void)download3
    {
        NSLog(@"%s----%@",__func__,[NSThread currentThread]);
    }
    
    @end
    #import "XMGOperation.h"
    
    @implementation XMGOperation
    
    //告知要执行的任务是什么
    //1.有利于代码隐蔽
    //2.复用性
    -(void)main
    {
        NSLog(@"main---%@",[NSThread currentThread]);
    }
    @end
    #import "ViewController.h"
    #import "XMGOperation.h"
    
    
    @interface ViewController ()
    /** 队列 */
    @property (nonatomic, strong) NSOperationQueue *queue;
    @end
    
    @implementation ViewController
    
    #pragma mark ----------------------
    #pragma mark Events
    
    /**
     * 1:先创建队列,设置最大并发数,来决定是串行还是并发,三种方式封装任务,将任务添加到队列(也可以快速实现封装任务到队列)2:任务的取消暂停
     *
     */
    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        [self test2];
    }
    
    - (IBAction)startBtnClick:(id)sender
    {
        //1.创建队列
        //默认是并发队列
        self.queue = [[NSOperationQueue alloc]init];
        
        //2.设置最大并发数量 maxConcurrentOperationCount
        self.queue.maxConcurrentOperationCount = 1;
        
        XMGOperation *op1 = [[XMGOperation alloc]init];
        
        //4.添加到队列
        [self.queue addOperation:op1];
    }
    
    - (IBAction)suspendBtnClick:(id)sender
    {
        //暂停,是可以恢复
        /*
         队列中的任务也是有状态的:已经执行完毕的 | 正在执行 | 排队等待状态
         */
        //不能暂停当前正在处于执行状态的任务
        [self.queue setSuspended:YES];
    }
    
    - (IBAction)goOnBtnClick:(id)sender
    {
        //继续执行
        [self.queue setSuspended:NO];
    }
    
    - (IBAction)cancelBtnClick:(id)sender
    {
        //取消,不可以恢复
        //该方法内部调用了所有操作的cancel方法
        [self.queue cancelAllOperations];
    }
    
    
    -(void)test
    {
        //1.创建队列
        //默认是并发队列
        NSOperationQueue *queue = [[NSOperationQueue alloc]init];
        
        //2.设置最大并发数量 maxConcurrentOperationCount
        //同一时间最多有多少个任务可以执行
        //串行执行任务!=只开一条线程 (线程同步)
        // maxConcurrentOperationCount >1 那么就是并发队列
        // maxConcurrentOperationCount == 1 那就是串行队列
        // maxConcurrentOperationCount == 0  不会执行任务
        // maxConcurrentOperationCount == -1 特殊意义 最大值 表示不受限制
        queue.maxConcurrentOperationCount = 1;
        
        //3.封装操作
        NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"1----%@",[NSThread currentThread]);
        }];
        
        NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"2----%@",[NSThread currentThread]);
        }];
        
        NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"3----%@",[NSThread currentThread]);
        }];
        
        NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"4----%@",[NSThread currentThread]);
        }];
        
        NSBlockOperation *op5 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"5----%@",[NSThread currentThread]);
        }];
        NSBlockOperation *op6 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"6----%@",[NSThread currentThread]);
        }];
        NSBlockOperation *op7 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"7----%@",[NSThread currentThread]);
        }];
        
        //4.添加到队列
        [queue addOperation:op1];
        [queue addOperation:op2];
        [queue addOperation:op3];
        [queue addOperation:op4];
        [queue addOperation:op5];
        [queue addOperation:op6];
        [queue addOperation:op7];
    }
    
    -(void)test2
    {
        //1.创建队列
        //默认是并发队列
        self.queue = [[NSOperationQueue alloc]init];
        
        //2.设置最大并发数量 maxConcurrentOperationCount
        //同一时间最多有多少个任务可以执行
        //串行执行任务!=只开一条线程 (线程同步)
        // maxConcurrentOperationCount >1 那么就是并发队列
        // maxConcurrentOperationCount == 1 那就是串行队列
        // maxConcurrentOperationCount == 0  不会执行任务
        // maxConcurrentOperationCount == -1 特殊意义 最大值 表示不受限制
        self.queue.maxConcurrentOperationCount = 1;
        
        //3.封装操作
        NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
            for (NSInteger i = 0; i<1000; i++) {
                NSLog(@"1-%zd---%@",i,[NSThread currentThread]);
            }
        }];
        
        NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
            for (NSInteger i = 0; i<1000; i++) {
                NSLog(@"2-%zd---%@",i,[NSThread currentThread]);
            }
        }];
        
        NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
            for (NSInteger i = 0; i<1000; i++) {
                NSLog(@"3-%zd---%@",i,[NSThread currentThread]);
            }
        }];
        
        NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"4----%@",[NSThread currentThread]);
        }];
        
        NSBlockOperation *op5 = [NSBlockOperation blockOperationWithBlock:^{
            for (NSInteger i = 0; i<1000; i++) {
                NSLog(@"5-%zd---%@",i,[NSThread currentThread]);
            }
        }];
        NSBlockOperation *op6 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"6----%@",[NSThread currentThread]);
        }];
        NSBlockOperation *op7 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"7----%@",[NSThread currentThread]);
        }];
        
        //4.添加到队列
        [self.queue addOperation:op1];
        [self.queue addOperation:op2];
        [self.queue addOperation:op3];
        [self.queue addOperation:op4];
        [self.queue addOperation:op5];
        [self.queue addOperation:op6];
        [self.queue addOperation:op7];
    }
    
    -(void)demo
    {
    }
    
    @end

    - 2.2 NSOperationQueue基本使用

    (1)NSOperation中的两种队列

        01 主队列 通过mainQueue获得,凡是放到主队列中的任务都将在主线程执行

        02 非主队列 直接alloc init出来的队列。非主队列同时具备了并发和串行的功能,通过设置最大并发数属性来控制任务是并发执行还是串行执行

    (2)相关代码

    ```objc

    //自定义NSOperation

    -(void)customOperation

    {

        //1.创建队列

        NSOperationQueue *queue = [[NSOperationQueue alloc]init];

        //2.封装操作

        //好处:1.信息隐蔽

        //2.代码复用

        XMGOperation *op1 = [[XMGOperation alloc]init];

        XMGOperation *op2 = [[XMGOperation alloc]init];

        //3.添加操作到队列中

        [queue addOperation:op1];

        [queue addOperation:op2];

    }

    //NSBlockOperation

    - (void)block

    {

        //1.创建队列

        NSOperationQueue *queue = [[NSOperationQueue alloc]init];

        //2.封装操作

        NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{

            NSLog(@"1----%@",[NSThread currentThread]);

        }];

        NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{

            NSLog(@"2----%@",[NSThread currentThread]);

        }];

        [op2 addExecutionBlock:^{

            NSLog(@"3----%@",[NSThread currentThread]);

        }];

        [op2 addExecutionBlock:^{

            NSLog(@"4----%@",[NSThread currentThread]);

        }];

        //3.添加操作到队列中

        [queue addOperation:op1];

        [queue addOperation:op2];

        //补充:简便方法

        [queue addOperationWithBlock:^{

            NSLog(@"5----%@",[NSThread currentThread]);

        }];

    }

    //NSInvocationOperation

    - (void)invocation

    {

        /*

         GCD中的队列:

         串行队列:自己创建的,主队列

         并发队列:自己创建的,全局并发队列

         NSOperationQueue

         主队列:[NSOperationQueue mainqueue];凡事放在主队列中的操作都在主线程中执行

         非主队列:[[NSOperationQueue alloc]init],并发和串行,默认是并发执行的

         */

        //1.创建队列

        NSOperationQueue *queue = [[NSOperationQueue alloc]init];

        //2.封装操作

        NSInvocationOperation *op1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download1) object:nil];

        NSInvocationOperation *op2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download2) object:nil];

        NSInvocationOperation *op3 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download3) object:nil];

        //3.把封装好的操作添加到队列中

        [queue addOperation:op1];//[op1 start]

        [queue addOperation:op2];

        [queue addOperation:op3];

    }

    ```

    - 2.3 NSOperation其它用法

    (1)设置最大并发数【控制任务并发和串行】

    ```objc

    //1.创建队列

        NSOperationQueue *queue = [[NSOperationQueue alloc]init];

        //2.设置最大并发数

        //注意点:该属性需要在任务添加到队列中之前进行设置

        //该属性控制队列是串行执行还是并发执行

        //如果最大并发数等于1,那么该队列是串行的,如果大于1那么是并行的

        //系统的最大并发数有个默认的值,为-1,如果该属性设置为0,那么不会执行任何任务

        queue.maxConcurrentOperationCount = 2;

    ```

    (2)暂停和恢复以及取消

    ```objc

        //设置暂停和恢复

        //suspended设置为YES表示暂停,suspended设置为NO表示恢复

        //暂停表示不继续执行队列中的下一个任务,暂停操作是可以恢复的

        if (self.queue.isSuspended) {

            self.queue.suspended = NO;

        }else

        {

            self.queue.suspended = YES;

        }

        //取消队列里面的所有操作

        //取消之后,当前正在执行的操作的下一个操作将不再执行,而且永远都不在执行,就像后面的所有任务都从队列里面移除了一样

        //取消操作是不可以恢复的

        [self.queue cancelAllOperations];

    ---------自定义NSOperation取消操作--------------------------

    -(void)main

    {

        //耗时操作1

        for (int i = 0; i<1000; i++) {

            NSLog(@"任务1-%d--%@",i,[NSThread currentThread]);

        }

        NSLog(@"+++++++++++++++++++++++++++++++++");

        //苹果官方建议,每当执行完一次耗时操作之后,就查看一下当前队列是否为取消状态,如果是,那么就直接退出

        //好处是可以提高程序的性能

        if (self.isCancelled) {

            return;

        }

        //耗时操作2

        for (int i = 0; i<1000; i++) {

            NSLog(@"任务1-%d--%@",i,[NSThread currentThread]);

        }

        NSLog(@"+++++++++++++++++++++++++++++++++");

    }

    ```

  • 相关阅读:
    跟我一起学习ASP.NET 4.5 MVC4.0(二)(转)
    跟我一起学习ASP.NET 4.5 MVC4.0(一)(转)
    MVC3 Razor视图引擎的基础语法
    了解ASP.NET MVC几种ActionResult的本质:HttpStatusCodeResult & RedirectResult/RedirectToRouteResult
    通过一个模拟程序让你明白ASP.NET MVC是如何运行的
    ASP.NET中后台注册js脚本攻略(转)
    Python: 什么是*args和**kwargs
    配置mysql 及 设置密码
    java静态方法Static
    并发程序设计知识总结
  • 原文地址:https://www.cnblogs.com/cqb-learner/p/5851584.html
Copyright © 2020-2023  润新知