美文网首页
GCD相关概念总结(一)

GCD相关概念总结(一)

作者: CoderZxq | 来源:发表于2017-03-12 21:54 被阅读0次

    花了一天时间,看了Objective-C高级编程(iOS与OS X多线程和内存管理),对GCD有了初步的认识,大致有下面一些概念。

    Dispatch Queue

    分两类:Serial Dispatch Queue,Concurrent Dispatch Queue。Serial Dispatch Queue使用一个线程执行多个处理。Concurrent Dispatch Queue使用多个线程执行多个处理。

    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_after并不是在指定时间后执行处理,而是在指定时间追加处理到Dispatch Queue中。

    因为Main Dispatch Queue在主线程的RunLoop中执行,所以在比如每隔1/60秒执行的RunLoop中,Block最快3秒后执行,最慢在3秒+1/60秒后执行。

    扩展:dispatch_time(...)与dispatch_walltime(...)的区别,dispatch_time(...)通常用于计算相对时间,dispatch_walltime(...)计算绝对时间。

    Dispatch Group

    在追加到Dispatch Queue中的多个处理全部结束后执行结束处理。

    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(@"blk0")});
    dispatch_group_async(group, queue, ^{NSLog(@"blk1")});
    dispatch_group_async(group, queue, ^{NSLog(@"blk2")});
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{NSLog(@"done")});
    dispatch_release(group);
    

    无论向什么样的Dispatch Queue中添加处理,使用Dispatch Group都可监视这些处理执行的结束,一旦检测到所有处理执行结束,就可将结束的处理追加到Dispatch Queue中,这就是使用Dispatch Group的原因。

    dispatch_barrier_async

    在访问数据库或文件时,使用Concurrent Dispatch Queue会发生数据竞争,导致读取到与期待不符的数据,还可能因非法访问导致应用程序异常结束。 dispatch_barrier_async和Concurrent Dispatch Queue配合使用可实现高效率的数据库访问和文件访问。

    dispatch_barrier_async函数会等待追加到Concurrent Dispatch Queue上的并行执行的处理全部结束后,再将指定的处理追加到该Concurrent Dispatch Queue中,然后再由dispatch_barrier_async函数追加的处理执行完毕后,Concurrent Dispatch Queue才恢复为一般的动作,追加到该Concurrent Dispatch Queue的处理又开始并行执行。

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);  
    dispatch_async(queue, blk0_for_reading);
    dispatch_async(queue, blk0_for_reading);
    dispatch_async(queue, blk0_for_reading);
    dispatch_barrier_async(queue, blk0_for_writing);
    dispatch_async(queue, blk0_for_reading);
    dispatch_async(queue, blk0_for_reading);
    dispatch_async(queue, blk0_for_reading);
    

    dispatch_sync

    将指定的block处理“同步”追加到指定的Dispatch Queue中,在追加Block结束之前,dispatch_sync函数会一直等待,即当前线程停止。

    dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_sync(queue, ^{NSLog(@"Hello?");});
    

    以上源码会导致死锁

    dispatch_apply

    dispatch_apply函数是dispatch_sync和Dispatch Group的关联API,该函数按指定的次数将指定的Block追加到指定的Dispatch Queue中,并等待全部处理执行结束

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);  
    dispatch_apply(5, queue, ^(size_t index){NSLog(@"%zu", index);});
    NSLog(@"done");
    

    第一个参数为重复次数。第三个参数的Block为带有参数的Block,这是为了按第一个参数重复添加Block并区分各个Block耳使用的。

    dispatch_suspend / dispatch_resume

    挂起Dispatch Queue / 恢复Dispatch Queue

    这些函数对已经执行的处理没有影响,挂起后,追加到Dispatch Queue中但尚未执行的处理在此之后停止执行。而恢复则使得这些处理能够继续执行。

    Dispatch Semaphore

    持有计数的信号,计数为0时等待,计数为1或大于1时,减去1而不等待。

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);  
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
    NSMutableArray *array = [[NSMutableArray alloc] init];
    for (int i = 0; i < 1000; i ++) {
      dispatch_aync(queue, ^{
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        [array addObject:@(i)];
        dispatch_semaphore_signal(semaphore);
      })
    }
    dispatch_release(semaphore);
    

    dispatch_once

    dispatch_once函数是保证在应用程序执行中只执行一次指定处理的API。

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{/*初始化*/});
    

    Dispatch I/O

    多线程并发分块读取大文件。

    相关文章

      网友评论

          本文标题:GCD相关概念总结(一)

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