美文网首页
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}
    

    相关文章

      网友评论

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

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