NSOperation多线程的使用与理解

来源:互联网 发布:成达工程公司 知乎 编辑:程序博客网 时间:2024/05/22 06:58

GCD的操作不受人为控制,NSOpertion可以控制操作的暂停,取消,添加.



1.是一个抽象的类,不能直接使用.只有定义,没有实现.

2. 作为父类,约束子类的一些共有的属性和方法

3. 两个子类:

    NSInvocationOperation

    NSBlockOperation

4. 队列 : NSOperationQueue,默认是并发队列;

5. OP的核心 : 将操作添加到队列中

     两种写法:1---这种写法不能获取操作对象

        [self.queueaddOperationWithBlock:^{

            // 查看当前的线程

            NSLog(@"%d %@",i,[NSThreadcurrentThread]);

        }];


         方法2------------

    NSOperationQueue *queue = [[NSOperationQueuealloc]init];

    

    // 子类NSBlockOperation创建操作对象 :默认是异步的

    NSBlockOperation *op = [NSBlockOperationblockOperationWithBlock:^{

        // 查看当前的线程

        NSLog(@"%@",[NSThreadcurrentThread]);

    }];

    

    // 将操作添加到队列

    [queue addOperation:op];


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

    //子类 NSInvocationOperation创建操作对象

    NSInvocationOperation *op = [[NSInvocationOperationalloc]initWithTarget:selfselector:@selector(demo:)object:nil];

    

    // 创建队列

    NSOperationQueue *queue = [[NSOperationQueuealloc]init];

    

    // 将操作对象添加到队列

    [queue addOperation:op];




6. GCD的核心 : 将任务添加到队列

7.NSOperationQueue的操作默认是异步的,会开启新线程,

8. 回到主线程更新UI

        [[NSOperationQueuemainQueue]addOperationWithBlock:^{

            // 查看当前的线程

            NSLog(@"更新UI...%@",[NSThreadcurrentThread]);

        }];


9. 设置队列的最大并发数(限制同时执行的任务数量)

  间接控制了线程的数量,最少2个线程.但是不会开太多

       

[[NSOperationQueue allocinit].maxConcurrentOperationCount = 2;

   或者     

[[[NSOperationQueue allocinit] setMaxConcurrentOperationCount:2];




注意:操作对象默认在主线程中执行,只有添加到队列中才会开启新的线程。即默认情况下,如果操作没有放到队列中queue中,都是同步执行。只有将NSOperation放到一个NSOperationQueue中,才会异步执行操作 



10.暂停队列

// 表示队列"暂时"不能调度操作执行

    // 正在执行的操作不能被暂停

    // operationCount : 表示队列中的操作个数

    // 计算的是队列中正在执行和,没有执行的操作的总个数.执行完成的操作不会计算在内

    // 注意 :不要先暂停队列,一旦先暂停了队列,那么队列是不会去调度操作执行的

    self.queue.suspended =YES;


11.取消队列

    //取消队列中的全部操作  :正在执行的操作是无法取消的

    // 如果想取消需要自定义NSOperation

    // 类似于字典中移除全部的对象

    // 调用这个方法,表示队列向队列中的所有操作发送cancel消息

    

    // 这个方法有延迟时间

    [self.queue cancelAllOperations];


12.设置操做的优先级 :优先级最高

    // 同样的不能够决定操作的执行的先后顺序.决定这个操作有更多的机会被调度执行

    op1.qualityOfService =NSQualityOfServiceUserInteractive;

// NSQualityOfServiceBackground优先级最低

    op2.qualityOfService =NSQualityOfServiceBackground;



13.// 监听操作是否执行结束 ,如果结束会调用这个方法:这个操作是在子线程执行的

    [op1 setCompletionBlock:^{

        // 查看当前的线程

        NSLog(@"操作执行结束 %@",[NSThreadcurrentThread]);

    }];



13.操作间的依赖

    // 创建登陆操作

    NSBlockOperation *op1 = [NSBlockOperationblockOperationWithBlock:^{

        // 查看当前的线程

        NSLog(@"登陆 %@",[NSThreadcurrentThread]);

    }];

   

    // 创建付费操作

    NSBlockOperation *op2 = [NSBlockOperationblockOperationWithBlock:^{

        // 查看当前的线程

        NSLog(@"付费 %@",[NSThreadcurrentThread]);

    }];

    

    // 创建下载操作

    NSBlockOperation *op3 = [NSBlockOperationblockOperationWithBlock:^{

        // 查看当前的线程

        NSLog(@"下载 %@",[NSThreadcurrentThread]);

    }];

    

    // 创建通知用户的操作

    NSBlockOperation *op4 = [NSBlockOperationblockOperationWithBlock:^{

        // 查看当前的线程

        NSLog(@"通知用户 %@",[NSThreadcurrentThread]);

    }];

    

    // 建立依赖关系

    // 付费依赖登陆

    [op2 addDependency:op1];

    // 下载依赖付费

    [op3 addDependency:op2];

    // 通知用户依赖下载

    [op4 addDependency:op3];

    

   

    //登陆是不需要依赖任何操作的

    // 如果登陆依赖通知用户,就是循环依赖,此时,队列是不会调度任务执行的

    // 注意 : 绝对不能做

//    [op1 addDependency:op4];

    

    // 统一的将操作添加到队列

    // waitUntilFinished : 表示是否等待前面的任务执行结束,在执行后面的任务

    [self.queueaddOperations:@[op1,op2,op3]waitUntilFinished:NO];

    

    // 将通知用户的操作添加到主队列中

    // 操作间的依赖是可以跨队列建立的

    [[NSOperationQueuemainQueue]addOperation:op4];

    

    // 注意 :千万不要在添加到队列之后,再建立依赖关系,因为队列已经在调度任务执行了


    

       



0 0
原创粉丝点击