关于GCD的API(2)

作者: 静谧的橘子 | 来源:发表于2017-11-12 13:44 被阅读10次

    4.dispatch_after

    想在指定时间后执行处理的情况,可使用dispatch_after函数来实现。

    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW,3ull * NSEC_PER_SEC);
    dispatch_after(time, dispatch_get_main_queue(),^{
         NSLog(@"waited at least three seconds");
    });
    

    第一个参数是指定时间用的dispatch_time_t类型的值。该值使用dispatch_time函数或dispatch_walltime函数作成。
    第二个参数指定要追加处理的Dispatch Queue.
    第三个参数指定记述要执行处理的Block。

    dispatch_after函数并不是在指定时间后执行处理,而只是在指定时间追加处理到Dispatch Queue。也就是说此源代码可以理解为,3秒后用dispatch_async函数追加Block到Main Dispatch Queue相同。

    因为Main Dispatch Queue在主线程的RunLoop中执行,所以在比如每隔1/60秒执行的RunLoop中,Block最快3秒后执行,最慢在3 + 1/60 秒后执行,并且Main Dispatch Queue有大量处理追加或主线程的处理本身有延迟时,这个时间会更长。

    所以dispatch_after在想大致延迟执行处理时,非常有效,在严格时间的要求下还是尽量不使用。

    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW,3ull * NSEC_PER_SEC);
    

    dispatch_time函数能够获取从第一个参数dispatch_time_t类型值中指定的时间开始,到第二个参数指定的毫微秒单位时间后的时间。

    dispatch_walltime函数由POSIX中使用的struct timeespec类型的时间得到dispatch_time_t类型的值。
    dispatch_time函数通常用于计算相对时间,而dispatch_walltime函数用于计算绝对时间。
    “ull”是C语言的数值字面亮,是显示表明类型时使用的字符串(表示“unsigned long long”)。

    5.Dispatch Group

    在追加到Dispatch Queue中的多个处理全部结束后想执行结束处理,在Serial Dispatch Queue实现简单,但是在使用Concurrent Dispatch Queue 时或同时使用多个Dispatch Queue时,就会变得复杂。
    这种情况下使用Dispatch Group:

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t groupQueue = dispatch_group_create();
    dispatch_group_async(groupQueue, queue, ^{
            NSLog(@"1");
    });
    dispatch_group_async(groupQueue, queue, ^{
            NSLog(@"2");
    });
    dispatch_group_async(groupQueue, queue, ^{
            NSLog(@"3");
    });
    dispatch_group_notify(groupQueue, dispatch_get_main_queue(), ^{
            NSLog(@"end");
    });
    

    因为向Concurrent Dispatch Queue追加处理,多个线程并行执行,所以追加处理的执行顺序不定。
    Dispatch Group函数一旦检测到所有处理执行结束,就可将结束的处理追加到Dispatch Queue中。
    dispatch_group_notify函数,第一个参数指定为要监视的Dispatch Group。在追加到该Dispatch Group的全部处理执行结束时,将第三个参数的Block追加到第二个参数的Dispatch Queue中。
    另外,在Dispatch Group中也可以使用dispatch_group_wait函数仅等待全部处理执行结束。
    这里的“等待”意味着一旦调用dispatch_group_wait函数,该函数就处于调用状态而不返回,即执行该函数的当前线程停止。也就是在经过函数中指定的时间或属于指定的Dispatch Group的处理全部执行结束之前,执行该函数的线程停止。

    dispatch_group_wait函数会返回long类型的一个值,为0时,代表Dispatch Group 的全部处理执行结束;不为0时,代表虽然经过了指定的时间,但是某一个处理还在执行中。

    当等待为时间为DISPATCH_TIME_FOREVER、由dispatch_group_wait函数返回时,由于属于Dispatch Group的处理必定全部执行结束,因此返回值恒为0。
    不过,一般情形下,还是推荐使用dispatch_group_notify函数,因为该函数可以简化源代码。

    6.dispatch_barrier_async

    在访问数据库或文件时,为了避免数据竞争,以及高效率的进行访问,读取处理追加到Concurrent Dispatch Queue中,写入处理在任一个读取处理没有执行的状态下,追加到Serial Dispatch Queue中即可。

    GCD提供很聪明简便的解决办法--dispatch_barrier_async函数。该函数同dispatch_queue_create函数生成的Concurrent Dispatch Queue一起使用。

    dispatch_async(queue, blk0_for_reading);
    dispatch_async(queue, blk1_for_reading);
    dispatch_async(queue, blk2_for_reading);
    dispatch_barrier_async(queue, blk_for_writing);
    dispatch_async(queue, blk3_for_reading);
    dispatch_async(queue, blk4_for_reading);
    

    像上述源代码所示,在将dispatch_barrier_async函数追加到Concurrent Dispatch Queue中以后,之前的并行执行的处理全部结束之后,然后执行dispatch_barrier_async,在该函数执行完毕时,Concurrent Dispatch Queue才恢复为一般的动作,才会追加到Concurrent Dispatch Queue的处理又开始并行执行。

    相关文章

      网友评论

        本文标题:关于GCD的API(2)

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