GCD

作者: 低吟浅唱1990 | 来源:发表于2016-06-09 18:08 被阅读205次

    GCD

    Grand Central Dispatch是异步执行任务的技术之一。
    GCD是苹果公司为多核的并行运算提出的解决方案
    GCD会自动利用更多的CPU内核(比如双核、四核)
    GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程)
    程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码

    一个例子

    <pre>
    dispatch_async(queue, ^{

        /*
         *长时间处理
         */
        
        /*
         *长时间处理结束,主线程使用该处理结果
         *
         */
        dispatch_async(dispatch_get_main_queue(), ^{
            /*
             *只在主线程中可以执行的结果
             *例如  更新UI
             */
        });
    });
    其中queue是队列
    block是任务
    

    </pre>

    在多线程编程中容易发生各种问题。比如多线程更新相同的数据、死锁、使用线程太多大量消耗内存等。采用GCD技术大大简化了复杂的多线程编程

    Dispatch Queue

    开发者要做的只是定义想执行的任务并追加到适当的Dispatch Queue中。
    <pre>
    dispatch_async(queue, ^{
    /*
    *想执行的任务
    */
    });
    </pre>
    任务的取出遵循队列的FIFO原则:先进先出,后进后出。
    另外在执行处理的时候存在两种Dispatch Queue,一种是等待现在执行中处理的Serial Dispatch Queue,另一种是不等待现在执行中处理的Concurrent Dispatch Queue。


    并行视图
并行视图 串行视图
串行视图

    创建 dispatch_queue_create()

    dispatch_queue_create(const char *label, dispatch_queue_attr_t attr)
    <pre>
    dispatch_queue_t queue = dispatch_queue_create("gcd", NULL);
    dispatch_queue_create("gcd", DISPATCH_QUEUE_CONCURRENT)

    </pre>
    注意:系统对于一个Serial Dispatch Queue就只生成并使用一个线程。如果生成200个Serial Dispatch Queue,那么就生成200个线程
    但是每个queue里面的多个任务还是一个一个的执行。
    多个线程更新相同数据是可以使用Serial Dispatch Queue

    Main Dispatch Queue/Global Dispatch Queue

    <pre>
    dispatch_get_main_queue();
    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

            //可并行执行的处理
            dispatch_async(dispatch_get_main_queue(), ^{
               //主线程中处理
            });
        });
    

    </pre>

    dispatch_set_target_queue

    dispatch_queue_create()生成的Queue,使用与默认优先级Global Dispatch Queue相同执行优先级的线程。而变更生成的Queue的执行优先级需要使用dispatch_set_target_queue这个函数

    <pre>
    dispatch_set_target_queue(<#dispatch_object_t object#>, <#dispatch_queue_t queue#>)
    指定第一个Queue与第二个Queue相同的优先级。
    </pre>

    dispatch_after

    <pre>
    在1s后将指定的block追加到Main Queue中执行

    dispatch_after函数是指定时间追加而不是指定时间处理

    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 1*NSEC_PER_SEC);
    dispatch_after(time, dispatch_get_main_queue(), ^{
    NSLog(@"wait");
    });
    </pre>

    Dispatch Group

    在追加到Dispatch Queue中的多个处理全部结束之后想执行结束处理,这种会经常出现。在使用Current Dispatch的情况下使用Dispatch Group就可以实现
    <pre>
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, queue, ^{
    NSLog(@"hehe1");
    });

    dispatch_group_async(group, queue, ^{
        NSLog(@"hehe2");
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"hehe3");
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"hehe4");
    });
    dispatch_group_notify(group, queue, ^{
        NSLog(@"over");
    });
    

    2016-06-09 17:21:02.564 GCD[2874:227806] hehe3
    2016-06-09 17:21:02.564 GCD[2874:227802] hehe2
    2016-06-09 17:21:02.564 GCD[2874:227804] hehe1
    2016-06-09 17:21:02.564 GCD[2874:227813] hehe4
    2016-06-09 17:21:02.565 GCD[2874:227813] over
    </pre>
    多个线程并行执行,所以追加处理执行的顺序不定,但是 over一定在最后才执行这里有一个好例子给大家

    Dispatch Semaphore

    Dispatch Semaphore是持有计数的信号,该基数是多线程编程中的计数信号类型。当计数为0时等待,计数为1或者大于1,减去1而不等待。
    <pre>
    //创建一个计数为0的信号
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    NSMutableArray *muArray = [[NSMutableArray alloc] init];
    dispatch_async(queue, ^{
    for (int i=0; i<100; i++) {
    [muArray addObject:@(i)];
    }
    dispatch_semaphore_signal(semaphore); //计数+1
    });
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    NSLog(@"===>%d",[muArray count]);
    2016-06-09 17:49:14.300 GCD[2984:246535] ===>100
    如果没有则Dispatch Semaphore
    2016-06-09 17:57:55.160 GCD[3023:249929] ===>0
    </pre>
    上例中创建一个计数为0的信号 等待

    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);等待Dispatch Semaphore计数达到大于或者等于1。当计数达到或者大于1是,对该计数进行减法并从dispatch_semaphore_wait函数返回
    通过dispatch_semaphore_signal(semaphore); 将Dispatch Semaphore计数+1

    一个大神的GCD封装

    相关文章

      网友评论

        本文标题:GCD

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