美文网首页
GCD 任务与队列 同步异步、串行并行

GCD 任务与队列 同步异步、串行并行

作者: Cwwng | 来源:发表于2020-11-06 18:36 被阅读0次

1、什么是GCD?

GCD全称 Grand Central Dispatch,纯C语言API,提供非常强大的函数。

2、核心:任务和队列

将任务添加到队列,并且指定执行任务的函数。
任务:需要执行的操作。
队列:指执行任务的等待队列。是一种线性表,先进先出(FIFO)原则。

    // 任务
    dispatch_block_t block = ^{
        NSLog(@"Hello");
    };
    // 队列
    dispatch_queue_t queue = dispatch_queue_create("cwwng-queue", NULL);
    // 函数
    dispatch_async(queue, block);

同步与异步:
同步(dispatch_sync):必须等待当前语句执行完毕,才会执行下一条语句。不会开启线程,在当前线程执行block任务。
异步(dispatch_async):不用等待当前语句执行完毕,可执行下一条语句。会开启线程执行block任务。
注意:异步执行(async)具有开启新线程的能力,但是并不一定开启新线程,这跟任务所指定的队列类型有关。

串行队列与并发队列:
串行队列(Serial Dispatch Queue):每次只有一个任务被执行,任务按顺序一个接一个地执行。(只开启一个线程)
并发队列(Concurrent Dispatch Queue):可以让多个任务并发执行。(开启多个线程)

3、队列的类型

全局队列:是并发队列。
主队列:是一种特殊的串行队列。

    // 串行队列创建
    dispatch_queue_t queueSeial = dispatch_queue_create("com.seial", DISPATCH_QUEUE_SERIAL);
    // 并发队列创建
    dispatch_queue_t queueConcurrent = dispatch_queue_create("com.concurrent", DISPATCH_QUEUE_CONCURRENT);
    // 主队类获取
    dispatch_queue_t queueMain = dispatch_get_main_queue();
    // 全局队类获取
    dispatch_queue_t queueGlobal = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

4、任务的创建

    // 同步任务
    dispatch_sync(queueMain, ^{
        // 执行同步任务代码
    });
    // 异步任务
    dispatch_async(queueMain, ^{
        // 执行异步任务代码
    });

5、组合方式

串行队列+同步:不会开启新线程、任务逐步执行。
并发队列+同步:不会开启新线程、任务逐步执行。
主队列+同步:主线程调用,死锁。其他线程调用,不开启线程,逐步执行。
串行队列+异步:会开启一个新线程、任务逐步执行。
并发队列+异步:会开启多个新线程、多任务并发执行。
主队列+异步:不会开启新线程,任务逐步执行。

6、验证5代码

6.1、串行队列+同步

    // 不会开启新线程,在当前线程执行任务。任务是串行执行。
    dispatch_queue_t queueSeial = dispatch_queue_create("com.seial", DISPATCH_QUEUE_SERIAL);
    NSLog(@"currentThread - %@",[NSThread currentThread]);  // 打印当前线程
    // 串行队列 + 同步任务
    dispatch_sync(queueSeial, ^{
        sleep(4);
        NSLog(@"1 - %@",[NSThread currentThread]);
    });
    dispatch_sync(queueSeial, ^{
        sleep(3);
        NSLog(@"2 - %@",[NSThread currentThread]);
    });
    dispatch_sync(queueSeial, ^{
        sleep(2);
        NSLog(@"3 - %@",[NSThread currentThread]);
    });
    dispatch_sync(queueSeial, ^{
        sleep(1);
        NSLog(@"4 - %@",[NSThread currentThread]);
    });
2020-11-06 17:17:06.200720+0800 Demo[19868:2048817] currentThread - <NSThread: 0x6000003702c0>{number = 1, name = main}
2020-11-06 17:17:10.201407+0800 Demo[19868:2048817] 1 - <NSThread: 0x6000003702c0>{number = 1, name = main}
2020-11-06 17:17:13.202940+0800 Demo[19868:2048817] 2 - <NSThread: 0x6000003702c0>{number = 1, name = main}
2020-11-06 17:17:15.204560+0800 Demo[19868:2048817] 3 - <NSThread: 0x6000003702c0>{number = 1, name = main}
2020-11-06 17:17:16.205038+0800 Demo[19868:2048817] 4 - <NSThread: 0x6000003702c0>{number = 1, name = main}

6.2、并发队列+同步

    //不会开启新线程,在当前线程中执行任务。任务是串行执行。
    dispatch_queue_t queueConcurrent = dispatch_queue_create("com.concurrent", DISPATCH_QUEUE_CONCURRENT);
    NSLog(@"currentThread - %@",[NSThread currentThread]);  // 打印当前线程
    // 并发队列 + 同步任务
    dispatch_sync(queueConcurrent, ^{
        sleep(4);
        NSLog(@"1 - %@",[NSThread currentThread]);
    });
    dispatch_sync(queueConcurrent, ^{
        sleep(3);
        NSLog(@"2 - %@",[NSThread currentThread]);
    });
    dispatch_sync(queueConcurrent, ^{
        sleep(2);
        NSLog(@"3 - %@",[NSThread currentThread]);
    });
    dispatch_sync(queueConcurrent, ^{
        sleep(1);
        NSLog(@"4 - %@",[NSThread currentThread]);
    });
2020-11-06 17:20:44.991766+0800 Demo[20023:2053209] currentThread - <NSThread: 0x60000207c1c0>{number = 1, name = main}
2020-11-06 17:20:48.993349+0800 Demo[20023:2053209] 1 - <NSThread: 0x60000207c1c0>{number = 1, name = main}
2020-11-06 17:20:51.995015+0800 Demo[20023:2053209] 2 - <NSThread: 0x60000207c1c0>{number = 1, name = main}
2020-11-06 17:20:53.996528+0800 Demo[20023:2053209] 3 - <NSThread: 0x60000207c1c0>{number = 1, name = main}
2020-11-06 17:20:54.998143+0800 Demo[20023:2053209] 4 - <NSThread: 0x60000207c1c0>{number = 1, name = main}

6.3、主队列+同步

6.3.1、主线程调用,死锁。

    dispatch_queue_t queueMain = dispatch_get_main_queue();
    NSLog(@"currentThread - %@",[NSThread currentThread]);  // 打印当前线程
    // 主队列 + 同步任务 + 主线程调用
    dispatch_sync(queueMain, ^{
        sleep(4);
        NSLog(@"1 - %@",[NSThread currentThread]);
    });
    dispatch_sync(queueMain, ^{
        sleep(3);
        NSLog(@"2 - %@",[NSThread currentThread]);
    });
    dispatch_sync(queueMain, ^{
        sleep(2);
        NSLog(@"3 - %@",[NSThread currentThread]);
    });
    dispatch_sync(queueMain, ^{
        sleep(1);
        NSLog(@"4 - %@",[NSThread currentThread]);
    });
2020-11-06 17:27:08.463180+0800 Demo[20300:2060486] currentThread - <NSThread: 0x600002ac4100>{number = 1, name = main}

6.3.2、其他线程调动

    // 不会开启新线程,在主线程中执行任务。任务是串行执行。
    // 全局队类获取
    dispatch_queue_t queueGlobal = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(queueGlobal, ^{
        NSLog(@"currentThread - %@",[NSThread currentThread]);  // 打印当前线程
        dispatch_queue_t queueMain = dispatch_get_main_queue();
        // 主队列 + 同步任务 + 其他线程线程调用
        dispatch_sync(queueMain, ^{
            sleep(4);
            NSLog(@"1 - %@",[NSThread currentThread]);
        });
        dispatch_sync(queueMain, ^{
            sleep(3);
            NSLog(@"2 - %@",[NSThread currentThread]);
        });
        dispatch_sync(queueMain, ^{
            sleep(2);
            NSLog(@"3 - %@",[NSThread currentThread]);
        });
        dispatch_sync(queueMain, ^{
            sleep(1);
            NSLog(@"4 - %@",[NSThread currentThread]);
        });
    });
2020-11-06 17:32:55.484067+0800 Demo[20583:2068194] currentThread - <NSThread: 0x6000007c1040>{number = 4, name = (null)}
2020-11-06 17:32:59.497909+0800 Demo[20583:2068085] 1 - <NSThread: 0x60000078c040>{number = 1, name = main}
2020-11-06 17:33:02.500238+0800 Demo[20583:2068085] 2 - <NSThread: 0x60000078c040>{number = 1, name = main}
2020-11-06 17:33:04.500890+0800 Demo[20583:2068085] 3 - <NSThread: 0x60000078c040>{number = 1, name = main}
2020-11-06 17:33:05.502132+0800 Demo[20583:2068085] 4 - <NSThread: 0x60000078c040>{number = 1, name = main}

6.4、串行队列+异步

    // 会开启一个新线程。任务是串行执行。
    dispatch_queue_t queueSeial = dispatch_queue_create("com.seial", DISPATCH_QUEUE_SERIAL);
    NSLog(@"currentThread - %@",[NSThread currentThread]);  // 打印当前线程
    // 异步任务
    dispatch_async(queueSeial, ^{
        sleep(4);
        NSLog(@"1 - %@",[NSThread currentThread]);
    });
    dispatch_async(queueSeial, ^{
        sleep(3);
        NSLog(@"2 - %@",[NSThread currentThread]);
    });
    dispatch_async(queueSeial, ^{
        sleep(2);
        NSLog(@"3 - %@",[NSThread currentThread]);
    });
    dispatch_async(queueSeial, ^{
        sleep(1);
        NSLog(@"4 - %@",[NSThread currentThread]);
    });
2020-11-06 18:19:31.378634+0800 Demo[20921:2077149] currentThread - <NSThread: 0x60000364c880>{number = 1, name = main}
2020-11-06 18:19:35.383806+0800 Demo[20921:2077231] 1 - <NSThread: 0x600003604100>{number = 4, name = (null)}
2020-11-06 18:19:38.384416+0800 Demo[20921:2077231] 2 - <NSThread: 0x600003604100>{number = 4, name = (null)}
2020-11-06 18:19:40.390142+0800 Demo[20921:2077231] 3 - <NSThread: 0x600003604100>{number = 4, name = (null)}
2020-11-06 18:19:41.393428+0800 Demo[20921:2077231] 4 - <NSThread: 0x600003604100>{number = 4, name = (null)}

6.5、并发队列+异步

    // 可开启多个线程。多任务并发执行。
    dispatch_queue_t queueConcurrent = dispatch_queue_create("com.concurrent", DISPATCH_QUEUE_CONCURRENT);
    NSLog(@"currentThread - %@",[NSThread currentThread]);  // 打印当前线程
    // 异步任务
    dispatch_async(queueConcurrent, ^{
        sleep(4);
        NSLog(@"1 - %@",[NSThread currentThread]);
    });
    dispatch_async(queueConcurrent, ^{
        sleep(3);
        NSLog(@"2 - %@",[NSThread currentThread]);
    });
    dispatch_async(queueConcurrent, ^{
        sleep(2);
        NSLog(@"3 - %@",[NSThread currentThread]);
    });
    dispatch_async(queueConcurrent, ^{
        sleep(1);
        NSLog(@"4 - %@",[NSThread currentThread]);
    });
2020-11-06 18:22:07.333160+0800 Demo[21040:2079918] currentThread - <NSThread: 0x600003160980>{number = 1, name = main}
2020-11-06 18:22:08.337539+0800 Demo[21040:2080046] 4 - <NSThread: 0x60000312fb00>{number = 7, name = (null)}
2020-11-06 18:22:09.336083+0800 Demo[21040:2080047] 3 - <NSThread: 0x600003121580>{number = 3, name = (null)}
2020-11-06 18:22:10.338269+0800 Demo[21040:2080049] 2 - <NSThread: 0x600003157240>{number = 8, name = (null)}
2020-11-06 18:22:11.338086+0800 Demo[21040:2080048] 1 - <NSThread: 0x600003128900>{number = 5, name = (null)}

6.6、主队列+异步

    // 不会开启新线程,在主线程中执行任务。任务是串行执行。
    dispatch_queue_t queueMian = dispatch_get_main_queue();
    NSLog(@"currentThread - %@",[NSThread currentThread]);  // 打印当前线程
    // 异步任务
    dispatch_async(queueMian, ^{
        sleep(4);
        NSLog(@"1 - %@",[NSThread currentThread]);
    });
    dispatch_async(queueMian, ^{
        sleep(3);
        NSLog(@"2 - %@",[NSThread currentThread]);
    });
    dispatch_async(queueMian, ^{
        sleep(2);
        NSLog(@"3 - %@",[NSThread currentThread]);
    });
    dispatch_async(queueMian, ^{
        sleep(1);
        NSLog(@"4 - %@",[NSThread currentThread]);
    });
2020-11-06 18:24:40.706290+0800 Demo[21155:2082720] currentThread - <NSThread: 0x60000130c340>{number = 1, name = main}
2020-11-06 18:24:44.811041+0800 Demo[21155:2082720] 1 - <NSThread: 0x60000130c340>{number = 1, name = main}
2020-11-06 18:24:47.812006+0800 Demo[21155:2082720] 2 - <NSThread: 0x60000130c340>{number = 1, name = main}
2020-11-06 18:24:49.813334+0800 Demo[21155:2082720] 3 - <NSThread: 0x60000130c340>{number = 1, name = main}
2020-11-06 18:24:50.813910+0800 Demo[21155:2082720] 4 - <NSThread: 0x60000130c340>{number = 1, name = main}

相关文章

  • IOS多线程总结

    目录 简述 NSThread GCD操作与队列异步操作并行队列同步操作并行队列同步操作串行队列异步操作串行队列队列...

  • 关于多线程GCD 串行/并行、同步/异步

    一、GCD串行/并行队列创建 串行队列: 并行队列: 二、GCD串行/并行队列同步/异步执行 执行内容1: 执行结...

  • 不可不说的多线程

    关键字:多线程原理,队列(串行并行),任务(同步异步),NSThread,GCD,NSOperation,@syn...

  • gcd多线程任务与队列组合分析

    关于gcd中串行队列并行队列,以及同步任务和异步任务的花式嵌套,分析执行结果 多线程调试常用代码: gcd的任务 ...

  • GCD基础总结一

    上代码~ 同步串行队列 同步并行队列 异步串行队列 异步并行队列 主队列同步 会卡住 主队列异步

  • 多线程

    iOS中的几种多线程GCD1、GCD分为任务和队列,任务(同步,异步)队列(串行,并发),同步串行,同步主队列的情...

  • 【iOS出租屋进阶】之多线程GCD详解

    线程、任务和队列的概念 异步、同步 & 并行、串行的特点 组合 |并行队列|串行队列 |主队列----|----|...

  • 多线程

    1、同步、异步、串行、并行、全局队列、主队列2、Thread、NSOperation、GCD3、锁

  • GCD

    1、同步串行队列 2、同步并行队列 3、异步串行队列 4、异步并行队列 5、死锁 主线程中创建同步串行队列 主线程...

  • GCD学习总结

    GCD容易混淆的概念 任务,同步,异步 ,串行队列,并发队列 任务就是要做的事情 同步和异步是用来执行任务的 串行...

网友评论

      本文标题:GCD 任务与队列 同步异步、串行并行

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