通俗易懂GCD

作者: 飞翔的小骑兵 | 来源:发表于2015-07-31 15:43 被阅读983次
    IOS三人行IOS三人行

    Dispatch Queue(调度队列)

    Serial Dispatch Queue串行代码;
    Concurrent Dispatch Queue并行代码。

    创建队列:

    1. 创建Serial Dispatch Queue。

    dispatch_queue_t serialQueue =
    dispatch_queue_create(“com.SerialQueue”, NULL);

    1. 创建Concurrent Dispatch Queue
    dispatch_queue_t concurrentQueue =
      dispatch_queue_create(“com.ConcurrentQueue”,
        DISPATCH_QUEUE_CONCURRENT);
    

    对于串行队列,每创建一个串行队列,系统就会对应创建一个线程,同时这些线程都是并行执行的,只是在串行队列中的任务是串行执行的。大量的创建串行队列会导致大量消耗内存,这是不可取的做法。串行队列的优势在于他是一个线程,所以在操作一个全局数据时候是线程安全的。当想并行执行而不发生数据竞争时候可以用并行队列操作

    Main&Global Dispatch Queue

    Main Dispatch Queue是在主线程中执行任务的Dispatch Queue。因为主线程只有1个,所以Main Dispatch Queue是Serial Dispatch Queue。追加到Main Dispatch Queue中的任务将在主线程的RunLoop中执行。因为是在主线程中执行,所以应该只将用户界面更新等一些必须在主线程中执行的任务追加到Main Dispatch Queue中。

    dispatch_queue_t dispatch_main_queue = dispatch_get_main_queue();
    

    global Dispatch Queue是所有应用程序都能使用的Concurrent Dispatch Queue。大多数情况下,可以不必通过dispatch_queue_create函数生成Concurrent Dispatch Queue,而是只要获取Global Dispatch Queue使用即可。Global Dispatch Queue有4个优先级,分别是:High、Default、Low、Background。

    dispatch_queue_t dispatch_global_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    

    dispatch_group

    如果想在dispatch_queue中所有的任务执行完成后在做某种操作,在串行队列中,可以把该操作放到最后一个任务执行完成后继续,但是在并行队列中怎么做呢。这就有dispatch_group 成组操作。比如

        dispatch_queue_t dispatchQueue = dispatch_queue_create("ted.queue.next", DISPATCH_QUEUE_CONCURRENT);
        dispatch_group_t dispatchGroup = dispatch_group_create();
        dispatch_group_async(dispatchGroup, dispatchQueue, ^(){
            NSLog(@"dispatch-1");
        });
        dispatch_group_async(dispatchGroup, dispatchQueue, ^(){
            NSLog(@"dspatch-2");
        });
        dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^(){
            NSLog(@"end");
        });
    

    上面的 log1 和log2输出顺序不定,因为是在并行队列上执行,当并行队列全部执行完成后,最后到main队列上执行一个操作,保证“end”是最后输出。 另外,这里也可以不用创建自己的并行队列,用全局的global,那个也是个并行队列. dispatch_get_gloable_queue(0,0);

    dispatch_barrier_async

     dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
        dispatch_async(concurrentQueue, ^(){
            NSLog(@"dispatch-1");
        });
        dispatch_async(concurrentQueue, ^(){
            NSLog(@"dispatch-2");
        });
        dispatch_barrier_async(concurrentQueue, ^(){
            NSLog(@"dispatch-barrier"); 
        });
        dispatch_async(concurrentQueue, ^(){
            NSLog(@"dispatch-3");
        });
        dispatch_async(concurrentQueue, ^(){
            NSLog(@"dispatch-4");
        });
    

    dispatch_barrier_async 作用是在并行队列中,等待前面两个操作并行操作完成,这里是并行输出
    dispatch-1,dispatch-2
    然后执行
    dispatch_barrier_async中的操作,(现在就只会执行这一个操作)执行完成后,即输出
    "dispatch-barrier,
    最后该并行队列恢复原有执行状态,继续并行执行
    dispatch-3,dispatch-4

    dispatch_async 和dispatch_sync

    dispatch_sync(),同步添加操作。他是等待添加进队列里面的操作完成之后再继续执行。

        dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
        NSLog(@"1");
        dispatch_sync(concurrentQueue, ^(){
            NSLog(@"2");
            [NSThread sleepForTimeInterval:10];
            NSLog(@"3");
        });
        NSLog(@"4");
    

    输出 :

    11:36:25.313 GCDSeTest[544:303] 1
    
    11:36:25.313 GCDSeTest[544:303] 2
    
    11:36:30.313 GCDSeTest[544:303] 3//模拟长时间操作
    
    11:36:30.314 GCDSeTest[544:303] 4
    

    dispatch_async ,异步添加进任务队列,它不会做任何等待

        dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
        NSLog(@"1");
        dispatch_async(concurrentQueue, ^(){
            NSLog(@"2");
            [NSThread sleepForTimeInterval:5];
            NSLog(@"3");
        });
        NSLog(@"4");
    

    输出:

    11:42:43.820 GCDSeTest[568:303] 1
    
    11:42:43.820 GCDSeTest[568:303] 4
    
    11:42:43.820 GCDSeTest[568:1003] 2
    
    11:42:48.821 GCDSeTest[568:1003] 3//模拟长时间操作时间
    

    dispatch_after

    dispatch_after能让我们添加进队列的任务延时执行,比如想让一个Block在10秒后执行:

    var time = dispatch_time(DISPATCH_TIME_NOW, (Int64)(10 * NSEC_PER_SEC))
    
    dispatch_after(time, globalQueue) { () -> Void in
    
        println("在10秒后执行")
    
    } 
    
    

    需要注意的是,使用dispatch_after实现延迟执行某动作,时间并不是很精确,实际上是过多久将Block追加到main Queue中,而不是执行该动作,如果此时main queue中的任务很多,没有执行完毕,那么新添加的这个动作就要继续推迟

    相关文章

      网友评论

        本文标题:通俗易懂GCD

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