[New learn] NSOperation基本使用

1.简介

NS(基于OC语言)是对GCD(基于C语言)的封装,让开发者能够更加友好的方便的去使用多线程技术。

2.NSOperation的基本使用

NSOperation是抽象类,所以如果要使用NSOperation则需要继承和实现它。

内置的子类常用的有两个:

  • NSInvocationOperation
  • NSBlockOperation

使用步骤:

  无论上述哪一个一般使用都遵循以下步骤:

  1. 创建队列/获取主队列
  2. 创建子类实例
  3. 加入队列

例子:https://github.com/xufeng79x/NSOperation

3.NSOperation再研究

NSOperation 中有这么一句话:

An operation object is a single-shot object—that is, it executes its task once and cannot be used to execute it again.

所以说一个操作只能被执行一次,当如下代码将某个操作加到多个队列的时候会出现错误

[queue1 addOperation:op1];

[queue2 addOperation:op1];

错误:

2016-03-01 16:30:40.425 NSOperation-Test[2430:148961] *** Terminating app due to uncaught exception ‘NSInvalidArgumentException‘, reason: ‘*** -[NSOperationQueue addOperation:]: operation is already enqueued on a queue‘

4.线程间通信

和GCD一样,当在某个线程中获取到信息需要更新UI的时候,那么更新UI需要在主线程中进行,所以这个就涉及到线程间的通信。

// MARK: 线程间通信

- (void) test_threads_com
{
    //1. 创建队列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    //2. 在其他形成做耗时操作
    [queue addOperationWithBlock:^{
        NSLog(@"耗时操作---------%@", [NSThread currentThread]);

        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            NSLog(@"更新UI---------%@", [NSThread currentThread]);
        }];
    }];
}

上述代码通过队列的不同从而让人物去在不同线程中执行,main队列中的人物都是在主线程中执行的。

5.高级操作

介绍最大并发数,挂起,取消全部线程

注意:以上都是在队列上操作的,只对队列中未运行的线程其作用,而对正在运行和已经运行完毕的线程无效。

最大并发数:

// MARK:最大并发数
- (void)test_MaxThreadsNum
{
    //1. 创建队列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    //2. 设定队列上的最大并发数
    [queue setMaxConcurrentOperationCount:2];

    for (int i = 0; i < 20; i++) {
        //3. 直接将operation放到queue中
        [queue addOperationWithBlock:^{
            [NSThread sleepForTimeInterval:5.0f];
            NSLog(@"------------%@-------%d", [NSThread currentThread], i);
        }];
    }
}

输出:

可以看到每一次只有两个线程运行。

挂起:

// MARK:挂起
// 测试步骤:新增全局队列,运行的时候点击暂停/开始按钮来让队列挂起或者取消挂起
- (void)test_suspend
{
    // 设定最大并发数,便于观察
    [self.globQueue setMaxConcurrentOperationCount:2];
    for (int i = 0; i < 20; i++) {
        //1直接将operation放到queue中
        [self.globQueue addOperationWithBlock:^{
            [NSThread sleepForTimeInterval:5.0f];
            NSLog(@"------------%@-------%d", [NSThread currentThread], i);
        }];
    }
}

测试结果:

当程序运行的时候点击【暂定】后程序不再运行队列中的操作,当我们再次点击【开始】后继续运行队列中剩余的操作。

如前所述,挂起操作也是对于队列中的操作,而对已经运行的操作则不影响,所以我们看到暂停日志后又有两个任务打印出了结束日志。

另外一个细节就是当点击暂定时候队列中显示还有16个,再次点击开始的时候发现队列中还有14个,这说明只有当操作运行完毕后才会从队列中移除。

取消全部:

// MARK:取消全部
// 测试步骤:点击取消全部按钮
- (void)test_cancelALl
{
    // 设定最大并发数,便于观察
    [self.globQueue setMaxConcurrentOperationCount:2];
    for (int i = 0; i < 20; i++) {
        //1直接将operation放到queue中
        [self.globQueue addOperationWithBlock:^{
            [NSThread sleepForTimeInterval:5.0f];
            NSLog(@"------------%@-------%d", [NSThread currentThread], i);
        }];
    }
}

测试结果:

2016-03-04 11:20:06.469 NSOperation-Test[1379:43730] ------------<NSThread: 0x7b297590>{number = 6, name = (null)}-------0
2016-03-04 11:20:06.469 NSOperation-Test[1379:43912] ------------<NSThread: 0x7b2803d0>{number = 7, name = (null)}-------1
2016-03-04 11:20:10.084 NSOperation-Test[1379:43511] the queue has been cancelall! 18 in queue now!
2016-03-04 11:20:11.471 NSOperation-Test[1379:43912] ------------<NSThread: 0x7b2803d0>{number = 7, name = (null)}-------3
2016-03-04 11:20:11.471 NSOperation-Test[1379:43730] ------------<NSThread: 0x7b297590>{number = 6, name = (null)}-------2
2016-03-04 11:20:12.351 NSOperation-Test[1379:43511] the queue has been cancelall! 0 in queue now!

可以看到当运行的时候点击取消后后续所有任务都不会再运行。

值得注意的是点击取消后,还有运行日志打出,还是和之前所述一样,取消全部不会影响正在运行的操作。

另外需要注意的是,当点击取消的时候,日志还显示还有18个任务,当正在运行的操作完毕后,再次点击取消则显示为0个。

说明只有运行的任务运行完毕后才会清空队列。

思考--队列中的任务会按序执行吗?

// MARK:是否按序执行
- (void)test_executeOrder
{
    // 设定最大并发数为1,便于观察
    [self.globQueue setMaxConcurrentOperationCount:1];
    for (int i = 0; i < 20; i++) {
        //1直接将operation放到queue中
        [self.globQueue addOperationWithBlock:^{
            //[NSThread sleepForTimeInterval:1.0f];
            NSLog(@"------------%@-------%d", [NSThread currentThread], i);
        }];
    }
}

日志:

2016-03-04 11:32:25.530 NSOperation-Test[1465:48115] ------------<NSThread: 0x7a644ae0>{number = 3, name = (null)}-------0
2016-03-04 11:32:25.531 NSOperation-Test[1465:48115] ------------<NSThread: 0x7a644ae0>{number = 3, name = (null)}-------1
2016-03-04 11:32:25.531 NSOperation-Test[1465:48115] ------------<NSThread: 0x7a644ae0>{number = 3, name = (null)}-------2
2016-03-04 11:32:25.531 NSOperation-Test[1465:48115] ------------<NSThread: 0x7a644ae0>{number = 3, name = (null)}-------3
2016-03-04 11:32:25.531 NSOperation-Test[1465:48115] ------------<NSThread: 0x7a644ae0>{number = 3, name = (null)}-------4
2016-03-04 11:32:25.532 NSOperation-Test[1465:48115] ------------<NSThread: 0x7a644ae0>{number = 3, name = (null)}-------5
2016-03-04 11:32:25.532 NSOperation-Test[1465:48115] ------------<NSThread: 0x7a644ae0>{number = 3, name = (null)}-------6
2016-03-04 11:32:25.532 NSOperation-Test[1465:48115] ------------<NSThread: 0x7a644ae0>{number = 3, name = (null)}-------7
2016-03-04 11:32:25.532 NSOperation-Test[1465:48115] ------------<NSThread: 0x7a644ae0>{number = 3, name = (null)}-------8
2016-03-04 11:32:25.533 NSOperation-Test[1465:48115] ------------<NSThread: 0x7a644ae0>{number = 3, name = (null)}-------9
2016-03-04 11:32:25.533 NSOperation-Test[1465:48115] ------------<NSThread: 0x7a644ae0>{number = 3, name = (null)}-------10
2016-03-04 11:32:25.533 NSOperation-Test[1465:48115] ------------<NSThread: 0x7a644ae0>{number = 3, name = (null)}-------11
2016-03-04 11:32:25.533 NSOperation-Test[1465:48115] ------------<NSThread: 0x7a644ae0>{number = 3, name = (null)}-------12
2016-03-04 11:32:25.534 NSOperation-Test[1465:48115] ------------<NSThread: 0x7a644ae0>{number = 3, name = (null)}-------13
2016-03-04 11:32:25.534 NSOperation-Test[1465:48115] ------------<NSThread: 0x7a644ae0>{number = 3, name = (null)}-------14
2016-03-04 11:32:25.534 NSOperation-Test[1465:48115] ------------<NSThread: 0x7a644ae0>{number = 3, name = (null)}-------15
2016-03-04 11:32:25.535 NSOperation-Test[1465:48115] ------------<NSThread: 0x7a644ae0>{number = 3, name = (null)}-------16
2016-03-04 11:32:25.535 NSOperation-Test[1465:48115] ------------<NSThread: 0x7a644ae0>{number = 3, name = (null)}-------17
2016-03-04 11:32:25.535 NSOperation-Test[1465:48115] ------------<NSThread: 0x7a644ae0>{number = 3, name = (null)}-------18
2016-03-04 11:32:25.535 NSOperation-Test[1465:48115] ------------<NSThread: 0x7a644ae0>{number = 3, name = (null)}-------19

经过多次测试,发现是先进先出的有序执行。

 6.操作依赖

-线性依赖:

在NSOperation中可以进行操作的依赖设置,一个操作依赖于另外一个操作,可以在不同队列间的操作间设置依赖。

// MARK:操作间依赖
- (void)test_dependsLine
{
    //1. 建立第一个队列
    NSOperationQueue *queue1 = [[NSOperationQueue alloc]init];
    NSOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"------I am op1 in queue1------%@", [NSThread currentThread]);
    }];

    //2. 建立第二个队列
    NSOperationQueue *queue2 = [[NSOperationQueue alloc] init];
    NSOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"------I am op2 in queue2------%@", [NSThread currentThread]);
    }];

    //3. 建立第二个队列
    NSOperationQueue *queue3 = [[NSOperationQueue alloc] init];
    NSOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"------I am op3 in queue3------%@", [NSThread currentThread]);
    }];

    // 设定依赖关系
    [op3 addDependency:op2];
    [op2 addDependency:op1];

    // 一旦放入队列则将执行
    [queue1 addOperation:op1];
    [queue2 addOperation:op2];
    [queue3 addOperation:op3];
}

结果:

2016-03-05 00:26:01.803 NSOperation-Test[660:12848] ------I am op1 in queue1------<NSThread: 0x79f3b4b0>{number = 2, name = (null)}
2016-03-05 00:26:01.804 NSOperation-Test[660:12845] ------I am op2 in queue2------<NSThread: 0x79f39120>{number = 3, name = (null)}
2016-03-05 00:26:01.804 NSOperation-Test[660:12845] ------I am op3 in queue3------<NSThread: 0x79f39120>{number = 3, name = (null)}
2016-03-05 00:26:04.772 NSOperation-Test[660:12847] ------I am op1 in queue1------<NSThread: 0x7b217900>{number = 4, name = (null)}
2016-03-05 00:26:04.773 NSOperation-Test[660:12847] ------I am op2 in queue2------<NSThread: 0x7b217900>{number = 4, name = (null)}
2016-03-05 00:26:04.773 NSOperation-Test[660:12847] ------I am op3 in queue3------<NSThread: 0x7b217900>{number = 4, name = (null)}
2016-03-05 00:26:05.844 NSOperation-Test[660:12845] ------I am op1 in queue1------<NSThread: 0x79f39120>{number = 3, name = (null)}
2016-03-05 00:26:05.844 NSOperation-Test[660:12845] ------I am op2 in queue2------<NSThread: 0x79f39120>{number = 3, name = (null)}
2016-03-05 00:26:05.845 NSOperation-Test[660:12845] ------I am op3 in queue3------<NSThread: 0x79f39120>{number = 3, name = (null)}
2016-03-05 00:26:06.657 NSOperation-Test[660:12848] ------I am op1 in queue1------<NSThread: 0x79f3b4b0>{number = 2, name = (null)}
2016-03-05 00:26:06.658 NSOperation-Test[660:12848] ------I am op2 in queue2------<NSThread: 0x79f3b4b0>{number = 2, name = (null)}
2016-03-05 00:26:06.658 NSOperation-Test[660:12848] ------I am op3 in queue3------<NSThread: 0x79f3b4b0>{number = 2, name = (null)}
2016-03-05 00:26:07.608 NSOperation-Test[660:12848] ------I am op1 in queue1------<NSThread: 0x79f3b4b0>{number = 2, name = (null)}
2016-03-05 00:26:07.608 NSOperation-Test[660:12848] ------I am op2 in queue2------<NSThread: 0x79f3b4b0>{number = 2, name = (null)}
2016-03-05 00:26:07.609 NSOperation-Test[660:12848] ------I am op3 in queue3------<NSThread: 0x79f3b4b0>{number = 2, name = (null)}
2016-03-05 00:26:08.200 NSOperation-Test[660:12848] ------I am op1 in queue1------<NSThread: 0x79f3b4b0>{number = 2, name = (null)}
2016-03-05 00:26:08.202 NSOperation-Test[660:12848] ------I am op2 in queue2------<NSThread: 0x79f3b4b0>{number = 2, name = (null)}
2016-03-05 00:26:08.202 NSOperation-Test[660:12848] ------I am op3 in queue3------<NSThread: 0x79f3b4b0>{number = 2, name = (null)}
2016-03-05 00:26:08.566 NSOperation-Test[660:12848] ------I am op1 in queue1------<NSThread: 0x79f3b4b0>{number = 2, name = (null)}
2016-03-05 00:26:08.568 NSOperation-Test[660:12845] ------I am op2 in queue2------<NSThread: 0x79f39120>{number = 3, name = (null)}
2016-03-05 00:26:08.568 NSOperation-Test[660:12845] ------I am op3 in queue3------<NSThread: 0x79f39120>{number = 3, name = (null)}
2016-03-05 00:26:08.875 NSOperation-Test[660:12848] ------I am op1 in queue1------<NSThread: 0x79f3b4b0>{number = 2, name = (null)}
2016-03-05 00:26:08.876 NSOperation-Test[660:12848] ------I am op2 in queue2------<NSThread: 0x79f3b4b0>{number = 2, name = (null)}
2016-03-05 00:26:08.877 NSOperation-Test[660:12848] ------I am op3 in queue3------<NSThread: 0x79f3b4b0>{number = 2, name = (null)}

可以看到即使在不同的队列中操作依然按照设定的顺序执行。

-树形依赖

// MARK:操作间依赖-树形依赖
- (void)test_dependstree
{
    //1. 建立第一个队列
    NSOperationQueue *queue1 = [[NSOperationQueue alloc]init];
    NSOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"------I am op1 in queue1------%@", [NSThread currentThread]);
    }];

    //2. 建立第二个队列
    NSOperationQueue *queue2 = [[NSOperationQueue alloc] init];
    NSOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"------I am op2 in queue2------%@", [NSThread currentThread]);
    }];

    //3. 建立第二个队列
    NSOperationQueue *queue3 = [[NSOperationQueue alloc] init];
    NSOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"------I am op3 in queue3------%@", [NSThread currentThread]);
    }];

    // 设定依赖关系
    [op3 addDependency:op2];
    [op3 addDependency:op1];

    // 一旦放入队列则将执行
    [queue1 addOperation:op1];
    [queue2 addOperation:op2];
    [queue3 addOperation:op3];
}

结果:

2016-03-05 00:41:47.679 NSOperation-Test[712:16784] ------I am op2 in queue2------<NSThread: 0x78e2d160>{number = 3, name = (null)}
2016-03-05 00:41:47.679 NSOperation-Test[712:16785] ------I am op1 in queue1------<NSThread: 0x78e2bd70>{number = 2, name = (null)}
2016-03-05 00:41:47.680 NSOperation-Test[712:16784] ------I am op3 in queue3------<NSThread: 0x78e2d160>{number = 3, name = (null)}
2016-03-05 00:41:49.702 NSOperation-Test[712:16787] ------I am op1 in queue1------<NSThread: 0x79999660>{number = 4, name = (null)}
2016-03-05 00:41:49.703 NSOperation-Test[712:16785] ------I am op2 in queue2------<NSThread: 0x78e2bd70>{number = 2, name = (null)}
2016-03-05 00:41:49.703 NSOperation-Test[712:16785] ------I am op3 in queue3------<NSThread: 0x78e2bd70>{number = 2, name = (null)}
2016-03-05 00:41:50.165 NSOperation-Test[712:16787] ------I am op1 in queue1------<NSThread: 0x79999660>{number = 4, name = (null)}
2016-03-05 00:41:50.165 NSOperation-Test[712:16785] ------I am op2 in queue2------<NSThread: 0x78e2bd70>{number = 2, name = (null)}
2016-03-05 00:41:50.166 NSOperation-Test[712:16785] ------I am op3 in queue3------<NSThread: 0x78e2bd70>{number = 2, name = (null)}

可以看到op3需要等待op1和op2执行完毕后才会去执行。

-思考:可以先放队列在设定依赖吗?

// MARK:操作间依赖-先放队列后设定依赖
- (void)test_dependAfterQueued
{
    //1. 建立第一个队列
    NSOperationQueue *queue1 = [[NSOperationQueue alloc]init];
    NSOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"------I am op1 in queue1------%@", [NSThread currentThread]);
    }];

    //2. 建立第二个队列
    NSOperationQueue *queue2 = [[NSOperationQueue alloc] init];
    NSOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"------I am op2 in queue2------%@", [NSThread currentThread]);
    }];

    //3. 建立第二个队列
    NSOperationQueue *queue3 = [[NSOperationQueue alloc] init];
    NSOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"------I am op3 in queue3------%@", [NSThread currentThread]);
    }];

    // 一旦放入队列则将执行
    [queue1 addOperation:op1];
    [queue2 addOperation:op2];
    [queue3 addOperation:op3];

    // 设定依赖关系
    [op3 addDependency:op2];
    [op3 addDependency:op1];
}

结果:

2016-03-05 00:46:40.158 NSOperation-Test[747:18522] ------I am op2 in queue2------<NSThread: 0x7a66f630>{number = 2, name = (null)}
2016-03-05 00:46:40.158 NSOperation-Test[747:18521] ------I am op1 in queue1------<NSThread: 0x7b122120>{number = 4, name = (null)}
2016-03-05 00:46:40.158 NSOperation-Test[747:18523] ------I am op3 in queue3------<NSThread: 0x7b227d60>{number = 3, name = (null)}
2016-03-05 00:46:44.109 NSOperation-Test[747:18521] ------I am op3 in queue3------<NSThread: 0x7b122120>{number = 4, name = (null)}
2016-03-05 00:46:44.109 NSOperation-Test[747:18523] ------I am op1 in queue1------<NSThread: 0x7b227d60>{number = 3, name = (null)}
2016-03-05 00:46:44.109 NSOperation-Test[747:18585] ------I am op2 in queue2------<NSThread: 0x7b122600>{number = 5, name = (null)}
2016-03-05 00:46:45.555 NSOperation-Test[747:18521] ------I am op2 in queue2------<NSThread: 0x7b122120>{number = 4, name = (null)}
2016-03-05 00:46:45.555 NSOperation-Test[747:18523] ------I am op1 in queue1------<NSThread: 0x7b227d60>{number = 3, name = (null)}
2016-03-05 00:46:45.556 NSOperation-Test[747:18522] ------I am op3 in queue3------<NSThread: 0x7a66f630>{number = 2, name = (null)}
2016-03-05 00:46:47.417 NSOperation-Test[747:18522] ------I am op1 in queue1------<NSThread: 0x7a66f630>{number = 2, name = (null)}
2016-03-05 00:46:47.417 NSOperation-Test[747:18523] ------I am op2 in queue2------<NSThread: 0x7b227d60>{number = 3, name = (null)}
2016-03-05 00:46:47.417 NSOperation-Test[747:18585] ------I am op3 in queue3------<NSThread: 0x7b122600>{number = 5, name = (null)}
2016-03-05 00:46:49.218 NSOperation-Test[747:18522] ------I am op1 in queue1------<NSThread: 0x7a66f630>{number = 2, name = (null)}
2016-03-05 00:46:49.219 NSOperation-Test[747:18523] ------I am op3 in queue3------<NSThread: 0x7b227d60>{number = 3, name = (null)}
2016-03-05 00:46:49.218 NSOperation-Test[747:18585] ------I am op2 in queue2------<NSThread: 0x7b122600>{number = 5, name = (null)}

可以看到并没有按照依赖关系的顺序执行,所以说关系必须在操作放入队列之前需要提前设定。

时间: 2024-07-30 04:42:40

[New learn] NSOperation基本使用的相关文章

多线程之-NSOperation

多线程之-NSOperation NSOperation是个抽象类,并不具备封装操作的能力,必须使用它的子类 NSInvocationOperation 如果直接执行NSInvocationOperation中的操作, 那么默认会在主线程中执行 // 创建队列 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; // 创建操作 NSInvocationOperation *operation = [[NSInvocationOpe

IOS中的多线程【二】— NSOperation和NSOperationQueue

NSOperationQueue是一套基于Objective-c语言的API. GCD与NSOperationQueue的优缺点: NSOperationQueue:比较安全 GCD:没有NSOperationQueue安全,但使用起来简单,快速,还提供了一些操控底层的方法.实际开发中还是以GCD为主. NSOperationQueue实现多线程流程 1.定义一个任务队列. 2.定义一个任务. 3.把任务添加到队列中.一旦任务被添加到队列中,任务会马上被调度执行. 任务队列(NSOperatio

【Machine Learn】决策树案例:基于python的商品购买能力预测系统

决策树在商品购买能力预测案例中的算法实现 作者:白宁超 2016年12月24日22:05:42 摘要:随着机器学习和深度学习的热潮,各种图书层出不穷.然而多数是基础理论知识介绍,缺乏实现的深入理解.本系列文章是作者结合视频学习和书籍基础的笔记所得.本系列文章将采用理论结合实践方式编写.首先介绍机器学习和深度学习的范畴,然后介绍关于训练集.测试集等介绍.接着分别介绍机器学习常用算法,分别是监督学习之分类(决策树.临近取样.支持向量机.神经网络算法)监督学习之回归(线性回归.非线性回归)非监督学习(

iOS开发NSOperation 三:操作依赖和监听以及线程间通信

一:操作依赖和监听 #import "ViewController.h" @interface ViewController () @end @implementation ViewController /** * 1:NSOperation的使用:1:先创建队列NSOperationQueue:若不创建队列直接封装任务则默认在当前线程中串行执行任务,其队列分为两种主队列和非主队列,主队列和GCD中的主队列一样[NSOperationQueue mainQueue],而alloc in

TF.Learn

TF.Learn 手写文字识别 转载请注明作者:梦里风林Google Machine Learning Recipes 7官方中文博客 - 视频地址Github工程地址 https://github.com/ahangchen/GoogleML欢迎Star,也欢迎到Issue区讨论 mnist问题 计算机视觉领域的Hello world 给定55000个图片,处理成28*28的二维矩阵,矩阵中每个值表示一个像素点的灰度,作为feature 给定每张图片对应的字符,作为label,总共有10个la

线程2 NSOperation 抽像类的使用

// // ZYOperationViewController.h // Thread // // Created by yejiong on 14 // // ZYOperation.h // Thread // // Created by yejiong on 14/11/4. // Copyright © 2014年 zzz. All rights reserved. // #import <Foundation/Foundation.h> @interface ZYOperation

iOS中用GCD和NSOperation多个异步操作的关联

在iOS实际开发中,我们可能会遇到下面的场景:有以下四个操作A,B,C,D.要求A,B,C在子线程中执行,当A,B,C执行完毕之后回到主线程执行操作D,ABC之间可能会有相互依赖的关系,我们可以通过GCD和NSOperation都可以实现这样的需求. 1.GCD // 用GCD - (void)useGCD { // 1.1可以创建一个全局并发队列,A,B,C操作会在子线程中并发执行,ABC不存在先后执行顺序 // dispatch_queue_t quque=dispatch_get_glob

GCD和NSOperation 的概念,用法及之间的区别

CGD与NSOperation的区别 gcd是基于c的底层api,NSOperation属于object-c类.相对于gcd:1,NSOperation拥有更多的函数可用,具体查看api.2,在NSOperationQueue中,可以建立各个NSOperation之间的依赖关系.3,有kvo,可以监测operation是否正在执行(isExecuted).是否结束(isFinished),是否取消(isCanceld).4,NSOperationQueue可以方便的管理并发.NSOperatio

step 7 NSOperation(高级/GCD对比)

高级演练 全局队列 /// 全局操作队列,统一管理所有的异步操作 @property (nonatomic, strong) NSOperationQueue *queue; - (NSOperationQueue *)queue { if (_queue == nil) { _queue = [[NSOperationQueue alloc] init]; } return _queue; } 最大并发操作数 /// MARK: - 最大并发操作数 - (void)opDemo1 { // 设