美文网首页
GCD的一些使用

GCD的一些使用

作者: 我是好宝宝_6966 | 来源:发表于2019-03-06 11:33 被阅读0次

    1.主队列

    主队列是GCD自带的一种特殊的串行队列,放在主队列的任务都会在主线程中执行

    注意使用同步函数在主队列中执行,会造成线程死锁的情况

    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    dispatch_async(mainQueue, ^{
        NSLog(@"1");
    });
    dispatch_async(mainQueue, ^{
        NSLog(@"2");
    });
    dispatch_async(mainQueue, ^{
        NSLog(@"3");
    });
    dispatch_async(mainQueue, ^{
        NSLog(@"4");
    });
    

    结果:串行队列运行输出1234


    2.全局队列

    使用dispatch_get_global_queue函数获得全局的并发队列

    dispatch_queue_t defaultQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(defaultQueue, ^{
        NSLog(@"1");
    });
    dispatch_async(defaultQueue, ^{
        NSLog(@"2");
    });
    dispatch_async(defaultQueue, ^{
        NSLog(@"3");
    });
    dispatch_async(defaultQueue, ^{
        NSLog(@"4");
    });
    

    结果:并发队列随机输出2314


    3.自定义队列

    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.feng.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(concurrentQueue, ^{
        NSLog(@"1");
        dispatch_sync(concurrentQueue, ^{
            sleep(3);
            NSLog(@"2");
        });
        NSLog(@"3");
    });
    NSLog(@"4");
    
    

    结果:依次输出4123

    思路:由于新开了一个并行队列,先按顺序执行4;再执行并行队列里的代码1;因为2是个同步函数,所以3要在2之后执行


    4.单例

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        // 执行一次的操作代码
        NSLog(@"onceToken");
    });
    

    5.延迟执行

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"Hi");
    });
    

    结果:2秒后输出


    6.调度组dispatch_group_t(通常用于耗时操作)

    dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t defaultQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_async(group, defaultQueue, ^{
        sleep(3);
        NSLog(@"1");
    });
    dispatch_group_async(group, defaultQueue, ^{
        sleep(2);
        NSLog(@"2");
    });
    dispatch_group_notify(group, defaultQueue, ^{
        NSLog(@"4");
    });
    
    dispatch_group_enter(group);
    dispatch_async(defaultQueue, ^{
        sleep(1);
        NSLog(@"3");
        dispatch_group_leave(group);
    });
    

    结果:依次输出3214

    思路:(1)可以把并发队列123当成关卡group里的小怪,只有把关卡group里的小怪123全部打败才能离开关卡group去打BOSS4

    ​ (2)123执行没有先后,并发执行,只是sleep延后了

    ​ (3)等价关系

    dispatch_group_async(调度组, 队列, ^{
        do;
    });
    //等价于
    dispatch_group_enter(调度组);
    dispatch_async(defaultQueue, ^{
        do;
        dispatch_group_leave(调度组);
    });
    

    7.栅栏函数dispatch_barrier_async

    dispatch_queue_t queue = dispatch_queue_create("com.feng.barrierExecute", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        sleep(2);
        NSLog(@"1");
    });
    dispatch_async(queue, ^{
        sleep(3);
        NSLog(@"2");
    });
    dispatch_barrier_async(queue, ^{
        NSLog(@"3");
        sleep(2);
    });
    dispatch_async(queue, ^{
        sleep(2);
        NSLog(@"4");
    });
    

    结果:依次输出1234

    思路:栅栏函数的作用是调整代码执行顺序 barrier前->barrier->barrier后,即一个栅栏把一个关卡分成左右两边,左边的小怪杀完后,才可以通过栅栏;通过栅栏后才能打右边的小怪


    /*! dispatch_apply函数说明
     *  brief  dispatch_apply函数是dispatch_sync函数和Dispatch Group的关联API
     *  该函数按指定的次数将指定的Block追加到指定的Dispatch Queue中,并等到全部的处理执行结束
     *  
     *  @param 5    指定重复次数  指定10次
     *  @param queue 追加对象的Dispatch Queue
     *  @param index 带有参数的Block, index的作用是为了按执行的顺序区分各个Block
     *
     */
    dispatch_queue_t defaultQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_apply(5, defaultQueue, ^(size_t i) {
        NSLog(@"%lu", i);
    });
    NSLog(@"done");
    

    结果:随机输出12345,最后输出done

    思路:由于在global dispatch queue中执行,所以各个处理时间不固定,但dispatch_apply函数会等待所有处理结束,所以done一定出现在最后

    最后附上一张图

    相关文章

      网友评论

          本文标题:GCD的一些使用

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