美文网首页
GCD队列使用

GCD队列使用

作者: OC笔记 | 来源:发表于2016-11-01 14:50 被阅读0次

使用GCD前,先对队列总结一下:

串行和并发

GCD中队列分为两种:串行队列、并发队列。
串行队列:任务按在队列里的先后顺序执行,先进先出(FIFO),一个任务执行完成后,才会执行下一个任务(实际实现是在一个线程中完成所有任务,这个线程可能是主线程,也可能是子线程)。
并发队列:任务无序同时执行(实际实现是在多个子线程中执行)。

同步和异步

任务的执行方式分为同步和异步两种,同步和异步是以是否在当前线程执行区分的。
同步执行:任务都在当前线程中执行,并且会阻塞当前线程。
异步执行:任务会开辟新的线程,并在新的线程中执行,不会阻塞当前线程。

组合四种队列

两种队列和两种执行方式组合起来就形成了四种队列:串行同步队列、串行异步队列、并发同步队列、并发异步队列。四种队列区别如下(先贴结论,后面验证):

串行同步队列:任务都在当前线程执行(同步),并且顺序执行(串行)
串行异步队列:任务都在开辟的新的子线程中执行(异步),并且顺序执行(串行)
并发同步队列:任务都在当前线程执行(同步),但是是顺序执行的(并发的特性并没有体现出来)
并发异步队列:任务在开辟的多个子线程中执行(异步),并且是同时执行的(并发)

注:由上面的特性即可看出,我们平时对GCD使用最多的是并发异步队列。

准备工作

研究队列类型之间的区别前,先看一下GCD中生成队列的方法:
方法一:dispatch_queue_create:可以生成串行和并发队列

// 前两个方法生成的是串行队列;第三个生成的是并发队列
dispatch_queue_create("com.serial.queue", DISPATCH_QUEUE_SERIAL);
dispatch_queue_create("com.serial.queue", NULL);
dispatch_queue_create("com.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);

方法二:dispatch_get_global_queue:只能生成并发队列

// 只能生成并发队列
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

验证四种队列

打印方法:

#pragma mark - private methods
- (void)p_printThread:(int)index {
    NSLog(@"%@-------%d", [NSThread currentThread], index);
}

1.串行同步队列

dispatch_queue_t queue = dispatch_queue_create("com.serial.queue", NULL);
    dispatch_sync(queue, ^(){
        [self p_printThread:1];
    });
    dispatch_sync(queue, ^(){
        [self p_printThread:2];
    });
    dispatch_sync(queue, ^(){
        [self p_printThread:3];
    });
    dispatch_sync(queue, ^(){
        [self p_printThread:4];
    });

打印结果:

<NSThread: 0x608000068380>{number = 1, name = main}-------1
<NSThread: 0x608000068380>{number = 1, name = main}-------2
<NSThread: 0x608000068380>{number = 1, name = main}-------3
<NSThread: 0x608000068380>{number = 1, name = main}-------4

结论:在串行同步队列中,任务都在当前线程执行(同步),并且顺序执行(串行)。
注:打印的结果都是主线程,是因为当前线程是主线程,这并不是说同步就是在主线程执行的。

2.串行异步队列

dispatch_queue_t queue = dispatch_queue_create("com.serial.queue", DISPATCH_QUEUE_SERIAL);
    dispatch_async(queue, ^(){
        [self p_printThread:1];
    });
    dispatch_async(queue, ^(){
        [self p_printThread:2];
    });
    dispatch_async(queue, ^(){
        [self p_printThread:3];
    });
    dispatch_async(queue, ^(){
        [self p_printThread:4];
    });

打印结果:

 <NSThread: 0x60800007b440>{number = 3, name = (null)}-------1
 <NSThread: 0x60800007b440>{number = 3, name = (null)}-------2
 <NSThread: 0x60800007b440>{number = 3, name = (null)}-------3
 <NSThread: 0x60800007b440>{number = 3, name = (null)}-------4

结论:在串行异步队列中,任务都在新开辟的子线程中执行(异步),并且顺序执行(串行)。

3.并发同步队列

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_sync(queue, ^(){
        [self p_printThread:1];
    });
    dispatch_sync(queue, ^(){
        [self p_printThread:2];
    });
    dispatch_sync(queue, ^(){
        [self p_printThread:3];
    });
    dispatch_sync(queue, ^(){
        [self p_printThread:4];
    });

打印结果:

 <NSThread: 0x6080000790c0>{number = 1, name = main}-------1
 <NSThread: 0x6080000790c0>{number = 1, name = main}-------2
 <NSThread: 0x6080000790c0>{number = 1, name = main}-------3
 <NSThread: 0x6080000790c0>{number = 1, name = main}-------4

结论:在并发同步队列中,任务都在当前线程中执行(同步),但是是顺序执行的(并发的特性并没有体现出来,因为同步会阻塞当前线程)。

4.并发异步队列

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(queue, ^(){
        [self p_printThread:1];
    });
    dispatch_async(queue, ^(){
        [self p_printThread:2];
    });
    dispatch_async(queue, ^(){
        [self p_printThread:3];
    });
    dispatch_async(queue, ^(){
        [self p_printThread:4];
    });

打印结果:

 <NSThread: 0x618000066700>{number = 4, name = (null)}-------2
 <NSThread: 0x60000006cc80>{number = 6, name = (null)}-------4
 <NSThread: 0x60000006ccc0>{number = 3, name = (null)}-------1
 <NSThread: 0x6080000635c0>{number = 5, name = (null)}-------3

结论:在并发异步队列中,任务在多个新开辟的子线程中执行(异步),并且是同时无序地执行的(并发)

分析总结

由上面代码示例可以看出,串行队列就是在一个线程执行的队列:如果是当前线程,那就是串行同步队列(因为同步机制会阻塞当前线程),如果是新开辟的子线程,就是串行异步队列;并发队列如果是在当前线程中执行,就是并发同步队列,在新开辟的多个子线程中执行就是并发异步队列。
综上所述,我们平时使用最多的自然是并发异步队列,比如开辟多个子线程下载图片、文件等。

相关文章

  • iOS多线程--GCD篇

    GCD 文章目录GCD简介任务和队列GCD的使用步骤队列的创建方法任务的创建方法GCD的基本使用并行队列 + 同步...

  • iOS多线程--彻底学会多线程之『GCD』

    GCD 文章目录 GCD简介 任务和队列 GCD的使用步骤 队列的创建方法 任务的创建方法 GCD的基本使用 并行...

  • iOS GCD

    GCD 简介 GCD 任务和队列 GCD 的使用步骤 GCD 的基本使用(六种组合不同区别,队列嵌套情况区别,相互...

  • 多线程【转】

    文章目录GCD简介任务和队列GCD的使用步骤队列的创建方法任务的创建方法GCD的基本使用并行队列 + 同步执行并行...

  • NSOperation相关

    GCD和NSOperation比较 GCD :任务+队列步骤:创建队列--->使用函数将封装的任务添加到队列中 N...

  • iOS-多线程:GCD

    GCD 简介 GCD 任务和队列 GCD 的使用步骤 GCD 的基本使用(6种不同组合区别) GCD 线程间的通信...

  • GCD队列使用

    使用GCD前,先对队列总结一下: 串行和并发 GCD中队列分为两种:串行队列、并发队列。串行队列:任务按在队列里的...

  • GCD基础学习

    一、队列的创建和获取方式 GCD 的使用步骤 GCD 的使用步骤其实很简单,只有两步。创建一个队列(串行队列或并发...

  • 多线程之GCD使用

    上文已经介绍了GCD的一些基本概念多线程操作之GCD概述 GCD 的使用步骤 创建一个队列(串行队列或并发队列) ...

  • SDWebImage扩展笔记(一)

    SDWebImage中使用GCD主线程队列 GCD 如何安全获取主线程队列 获取主线程是 dispatch_get...

网友评论

      本文标题:GCD队列使用

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