GCD / NSOperation

 GCD 与 NSOperation 的区别 ?

1. GCD 是基于 C 语言写的核心服务, 非常简单高效, 而 NSOperation 是基于 GCD 的一种封装,抽象出来的对象, 所以一般情况下对于任务的依赖和并发数没有要求的情况下, GCD 的效率更高, 开销更小

2. 依赖关系,NSOperation可以设置两个NSOperation之间的依赖,第二个任务依赖于第一个任务完成执行,GCD无法设置依赖关系,不过可以通过dispatch_barrier_async来实现这种效果

3. KVO(键值对观察),NSOperation和容易判断Operation当前的状态(是否执行,是否取消),对此GCD无法通过KVO进行判断

4. 优先级,NSOperation可以设置自身的优先级,但是优先级高的不一定先执行,GCD只能设置队列的优先级,无法在执行的block设置优先级;

5. 继承,NSOperation是一个抽象类实际开发中常用的两个类是NSInvocationOperation和NSBlockOperation,同样我们可以自定义NSOperation,GCD执行任务可以自由组装,没有继承那么高的代码复用度;

总的来说: 如果对于任务的并发数和任务之间的依赖关系没有要求, 可以直接使用 GCD, 否则使用 NSOperation 可以满足对任务的控制

GCD

GCD 面对的不是线程, GCD 面对的只有队列和任务这两个概念, 你不用管在哪个线程, 只需要把任务按正确的同步/异步的方式添加进串行/并发队列即可

三种队列:

  • 串行队列(先进入队列的任务先出队列,每次只执行一个任务) 顺序执行
  • 并发队列(依然是“先入先出”,不过可以形成多个任务并发)   异步添加可以并发执行 同步添加只能顺序执行
  • 主队列(这是一个特殊的串行队列,而且队列中的任务一定会在主线程中执行)

两种执行方式:

  1. 同步执行  都不会开启新的线程
  2. 异步执行  会开启新的线程 除了主队列

          同步                          异步

主队列    死锁              不会开启新线程(顺序执行)

串行队列   在当前线程执行(顺序执行)     开启一个新的线程(顺序执行)      

并发队列   在当前线程执行(顺序执行)     开启一个或多个线程(并发执行)

下面是例子

//异步 + 并行队列

- (void)asyncConcurrent{

    //创建一个并行队列

    dispatch_queue_t queue = dispatch_queue_create("标识符", DISPATCH_QUEUE_CONCURRENT);

    NSLog(@"---start---");

    //使用异步函数封装三个任务

    dispatch_async(queue, ^{

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

    });

    dispatch_async(queue, ^{

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

    });

    dispatch_async(queue, ^{

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

    });

    NSLog(@"---end---");

}

结果:  start end  3 2 1  // 开启3个新的线程 同时执行的 没有先后

//异步 + 串行队列

- (void)asyncSerial{

    //创建一个串行队列

    dispatch_queue_t queue = dispatch_queue_create("标识符", DISPATCH_QUEUE_SERIAL);

    NSLog(@"---start---");

    //使用异步函数封装三个任务

    dispatch_async(queue, ^{

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

    });

    dispatch_async(queue, ^{

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

    });

    dispatch_async(queue, ^{

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

    });

    NSLog(@"---end---");

}

//  结果 start end 123   开启一个新的线程 顺序执行

//同步 + 并行队列

- (void)syncConcurrent{

    //创建一个并行队列

    dispatch_queue_t queue = dispatch_queue_create("标识符", DISPATCH_QUEUE_CONCURRENT);

    NSLog(@"---start---");

    //使用同步函数封装三个任务

    dispatch_sync(queue, ^{

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

    });

    dispatch_sync(queue, ^{

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

    });

    dispatch_sync(queue, ^{

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

    });

    NSLog(@"---end---");

// 结果 start 123 end  同步任务不会开启新线程也就没法并发执行  按顺序在一个单线程执行

// 同步+串行队列

- (void)syncSerial{

    //创建一个串行队列

    dispatch_queue_t queue = dispatch_queue_create("标识符", DISPATCH_QUEUE_SERIAL);

    NSLog(@"---start---");

    //使用异步函数封装三个任务

    dispatch_sync(queue, ^{

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

    });

    dispatch_sync(queue, ^{

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

    });

    dispatch_sync(queue, ^{

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

    });

    NSLog(@"---end---");

}

// 结果: start 123 end   跟同步串行一样 不能开启一个新的线程 只能在一个线程里按顺序执行

// 异步+ 主队列

- (void)asyncMain{

    //获取主队列

    dispatch_queue_t queue = dispatch_get_main_queue();

    NSLog(@"---start---");

    //使用异步函数封装三个任务

    dispatch_async(queue, ^{

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

    });

    dispatch_async(queue, ^{

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

    });

    dispatch_async(queue, ^{

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

    });

    NSLog(@"---end---");

}

// 结果 start 123 end  不会开启新的线程 会异步执行   主队列就运行在主线程

// 同步 + 主队列  死锁

*************************** GCD 实现所有异步操作完成之后执行的任务 *****************************

//先创建一个组

dispatch_group_t group = dispatch_group_create();

// 异步添加到任务到并行队列

dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

  //请求1 NSLog(@"Request_1");

});

dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

//请求2 NSLog(@"Request_2");

});

dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

//请求3 NSLog(@"Request_3");

});

// 当所有任务都执行完成之后 才执行

dispatch_group_notify(group, dispatch_get_main_queue(), ^{

//界面刷新 NSLog(@"任务均完成,刷新界面");

});

//  打印结果 2 1 3 刷新界面   会开启多线程 异步任务完成的顺序不受控制

*******************************如果需要添加任务之间的依赖**************************

  1. dispatch_group_t group =dispatch_group_create();
  2. dispatch_group_async(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
  3. NSLog(@"任务1");
  4. });
  5. dispatch_group_async(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
  6. NSLog(@"任务2");
  7. });
  8. dispatch_group_notify(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
  9. NSLog(@"任务3");
  10. });

//  任务 1 2 并行执行 执行完之后执行 3

  1. dispatch_queue_t myqueue =dispatch_queue_create("myqueue.queue",DISPATCH_QUEUE_CONCURRENT);
  2. dispatch_async(myqueue, ^{
  3. NSLog(@"任务1");
  4. });
  5. dispatch_async(myqueue, ^{
  6. NSLog(@"任务2");
  7. });
  8. dispatch_barrier_async(myqueue, ^{
  9. NSLog(@"任务3");
  10. });
  11. dispatch_async(myqueue, ^{
  12. NSLog(@"任务4");
  13. });
  14. dispatch_async(myqueue, ^{
  15. NSLog(@"任务5");
  16. });

//  1 2 并行执行 执行完之后执行3 最后执行 4 5

// *dispatch_barrier_async 会等待当前队列的任务执行完之后再执行dispatch_barrier_async(myqueue, ^{

  NSLog(@"任务3");

});

// NSOperation

NSOperation 实现多线程的使用步骤分为三步:

  1. 创建操作:先将需要执行的操作封装到一个 NSOperation 对象中。
  2. 创建队列:创建 NSOperationQueue 对象。
  3. 将操作加入到队列中:将 NSOperation 对象添加到 NSOperationQueue 对象中。

之后呢,系统就会自动将 NSOperationQueue 中的 NSOperation 取出来,在新线程中执行操作

使用NSOperation子类的方式有三种: 
NSInvocationOperation 
NSBlockOperation 
自定义子类继承NSOperation,实现响应的方法

先看看NSInvocationOperation的使用:

1. 同步执行的 直接操作 不加入 queue

NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(demo:) object:@"这是一个参数"];

[operation start]; }

/// 将参数与当前线程打印

- (void)demo:(NSString *)str { NSLog(@"%@--%@",str,[NSThread currentThread]); }

2. 加入队列 异步执行

// 创建操作队列

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

// 创建操作(最后的object参数是传递给selector方法的参数)

NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(demo:) object:@"这是一个参数"];

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

[operationQueue addOperation:operation]; }

/// 将参数与当前线程打印

- (void)demo:(NSString *)str { NSLog(@"%@--%@",str,[NSThread currentThread]); }

开启了一个子线程  且是异步执行的

只有将operation放到一个NSOperationQueue中,才会异步执行操作。

再看看NSBlockOperation

NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^(){ NSLog(@"%@",[NSThread currentThread]); }];

// 开始执行任务 [operation start];

// 直接執行 同步執行 不會開啟新線程//创建NSBlockOperation操作对象

22     NSBlockOperation *operation=[NSBlockOperation blockOperationWithBlock:^{
23         NSLog(@"NSBlockOperation------%@",[NSThread currentThread]);
24     }];
25
26     //添加操作  在子线程异步执行
27     [operation addExecutionBlock:^{
28         NSLog(@"NSBlockOperation1------%@",[NSThread currentThread]);
29     }];
30         // 在子线程 异步执行
31     [operation addExecutionBlock:^{
32         NSLog(@"NSBlockOperation2------%@",[NSThread currentThread]);
33     }];
34
35     //开启执行操作
36     [operation start];

// 為 operation 添加依賴關係

  1. NSOperationQueue *queue=[[NSOperationQueue alloc] init];
  2. //创建操作
  3. NSBlockOperation *operation1=[NSBlockOperation blockOperationWithBlock:^(){
  4. NSLog(@"执行第1次操作,线程:%@",[NSThread currentThread]);
  5. }];
  6. NSBlockOperation *operation2=[NSBlockOperation blockOperationWithBlock:^(){
  7. NSLog(@"执行第2次操作,线程:%@",[NSThread currentThread]);
  8. }];
  9. NSBlockOperation *operation3=[NSBlockOperation blockOperationWithBlock:^(){
  10. NSLog(@"执行第3次操作,线程:%@",[NSThread currentThread]);
  11. }];
  12. //添加依赖
  13. [operation1 addDependency:operation2];
  14. [operation2 addDependency:operation3];
  15. //将操作添加到队列中去
  16. [queue addOperation:operation1];
  17. [queue addOperation:operation2];
  18. [queue addOperation:operation3];

先執行3 然後 2 最後1  都是在同一個子線程執行的

// 设置最大并发数

 // 1.创建队列


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




    // 2.设置最大并发操作数


    queue.maxConcurrentOperationCount = 1// 串行队列


// queue.maxConcurrentOperationCount = 2; // 并发队列


// queue.maxConcurrentOperationCount = 8; // 并发队列




    // 3.添加操作


    [queue addOperationWithBlock:^{


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


            [NSThread sleepForTimeInterval:2]; // 模拟耗时操作


            NSLog(@"1---%@", [NSThread currentThread]); // 打印当前线程


        }


    }];


    [queue addOperationWithBlock:^{


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


            [NSThread sleepForTimeInterval:2]; // 模拟耗时操作


            NSLog(@"2---%@", [NSThread currentThread]); // 打印当前线程


        }


    }];


    [queue addOperationWithBlock:^{


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


            [NSThread sleepForTimeInterval:2]; // 模拟耗时操作


            NSLog(@"3---%@", [NSThread currentThread]); // 打印当前线程


        }


    }];


    [queue addOperationWithBlock:^{


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


            [NSThread sleepForTimeInterval:2]; // 模拟耗时操作


            NSLog(@"4---%@", [NSThread currentThread]); // 打印当前线程


        }


    }];

当最大并发操作数为1时,操作是按顺序串行执行的,并且一个操作完成之后,下一个操作才开始执行。当最大操作并发数为2时,操作是并发执行的,可以同时执行两个操作。而开启线程数量是由系统决定的,不需要我们来管理

 

NSBlockOperation最开始的任务是在主线程中执行的,再给NSBlockOperation添加的额外的任务是在子线程中执行的,程序自动帮助开启了子线程。

GCD队列和NSOperationQueue队列类型比较: 
GCD的队列类型: 
(1)并发队列:a.全局 b.自己创建的 
(2)串行队列:a.主队列 b.自己创建的 
NSOperationQueue队列类型: 
(1)主队列[NSOperationQueue mainQueue],添加到主队列中的任务,都会在主线程中执行。 
(2)其他队列(串行、并发),添加到其他队列中的任务,都会自动放在子线程中执行。

NSOperation默认是同步执行的。

原文地址:https://www.cnblogs.com/ChrisZhou666/p/8797504.html

时间: 2024-08-02 12:07:03

GCD / NSOperation的相关文章

iOS-多线程--(pthread/NSThread/GCD/NSOperation)--总结

零.线程的注意点(掌握)1.不要同时开太多的线程(1~3条线程即可,不要超过5条)2.线程概念1> 主线程 : UI线程,显示.刷新UI界面,处理UI控件的事件2> 子线程 : 后台线程,异步线程3.不要把耗时的操作放在主线程,要放在子线程中执行 一.NSThread(掌握)1.创建和启动线程的3种方式1> 先创建,后启动// 创建NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(dow

网络多线程(pthread , NSThread,GCD ,NSOperation)

在这里给大家介绍一些多线程的知识,以及应用,希望能给一些需要的朋友学习学习,如果有错误的地方,请帮忙指出,非常感谢. 那么先介绍多线程前,先说一下什么是线程,什么是进程? 进程:{ 1.正在运行的一个应用程序就叫进程. 2.每个进程之间都是相互独立的,每个进程都运行在自己独立的专用的且受保护的内存空间内. } 线程:{  1.线程是进程的基本执行单元. 2.每一个进程都默认开启一条线程,我们称之为主线程.(一个进程至少有一条线程) } 多线程:多线程就是一个进程可以开辟多线线程(子线程),同时执

线程间通信的三种方式(NSThread,GCD,NSOperation)

一.NSThread线程间通信 #import "ViewController.h" @interface ViewController ()<UIScrollViewDelegate> @property (strong, nonatomic) IBOutlet UIScrollView *scrollView; @property (weak, nonatomic)  UIImageView *imageView; @end @implementation ViewCo

ios30---pthread, NSThread, GCD, NSOperation

pthread(线程库,很早就有的技术,了解):一套通用的多线程API适用于Unix\Linux\Windows等系统(java开发也有pthread)跨平台\可移植使用难度大(全是C函数) C语言 程序员管理线程生命周期,几乎不用 NSThread(掌握):使用更加面向对象简单易用,可直接操作线程对象 OC语言 程序员管理线程生命周期(管生不管死),偶尔使用 GCD(功能强大,重点):旨在替代NSThread等线程技术充分利用设备的多核(特点) c语言 自动管理线程生命周期,经常使用 NSOp

iOS多线程(GCD NSOperation NSThread)

进程:进程是指在系统中正在运行的一个应用程序,每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内. 线程:1个进程要想执行任务,必须得有线程(每1个进程至少要有1条线程)线程是进程的基本执行单元,一个进程(程序)的所有任务都在线程中执行,比如使用酷狗播放音乐.使用迅雷下载电影,都需要在线程中执行.1个线程中任务的执行是串行的,如果要在1个线程中执行多个任务,那么只能一个一个地按顺序执行这些任务,也就是说,在同一时间内,1个线程只能执行1个任务,比如在1个线程中下载3个文件(分别是文

iOS GCD NSOperation NSThread等多线程各种举例详解(拷贝)

2年多的iOS之路匆匆而过,期间也拜读来不少大神的博客,近来突然为自己一直做伸手党感到羞耻,是时候回馈社会.回想当年自己还是小白的时候,照着一些iOS多线程教程学,也只是照抄,只知其然.不知其所以然.现写一篇详细教程奉献给广大读者.废话就不多说了,直接上干货.如下图列举了很多多线程的知识点,每个知识点都写有对应的详细例子,并对运行结果进行分析,绝对拿实践结果来说话.如果各位道友发现错误之处还请指正.附上demo下载地址 iOS中几种多线程的比较 GCD:是苹果为多核的并行运算提出的解决方案,所以

iOS 8:【转】NSOperation 笔记

源地址:http://fann.im/blog/2014/02/23/nsoperation/ iOS 下的多线程编程有 NSOperation 和 Grand Central Dispatch(GCD) 两种,简单记一些 NSOperation 的使用注意. NSOperationQueue 相当于一个操作池,operation 添加进来后会按照 First-In-First-Out(FIFO) 的策略自动执行.operation 一般会添加到应用全局共享的自定义 queue,这样避免阻塞主线

GCD的使用总结

什么是多线程? 计算机在运行一段程序的时候,会把该程序的CPU命令列配置到内存中,然后按照顺序一个一个执行命令列,这样1个CPU执行的CPU命令列为一条无分叉路径就是线程. 而有多条这样的执行指令列的路径存在时即为多线程. iOS实现多线程有4种方法: pthreads NSThread GCD NSOperation & NSOperationQueuef   这里我们主要讲GCD   一.Dispatch Queue和线程的关系 什么是Dispatch Queue? 如其名称,是执行处理的等

关于iOS多线程的总结

关于iOS多线程的总结 在这篇文章中,我将为你整理一下 iOS 开发中几种多线程方案,以及其使用方法和注意事项.当然也会给出几种多线程的案例,在实际使用中感受它们的区别.还有一点需要说明的是,这篇文章将会使用 Swift 和 Objective-c 两种语言讲解,双语幼儿园.OK,let's begin! 概述 这篇文章中,我不会说多线程是什么.线程和进程的区别.多线程有什么用,当然我也不会说什么是串行.什么是并行等问题,这些我们应该都知道的. 在 iOS 中其实目前有 4 套多线程方案,他们分