浅谈GCD

作者: 危险地带_浅笑 | 来源:发表于2016-03-23 21:45 被阅读75次

    出来工作已经一段时间了,但是对于大四才转程序的我,对很多程序方面的问题还是似懂非懂。很多时候学习起来也很迷茫,不知道自己往哪方面发展。于是乎很早之前就开始筹划写一些博客记录自己学习的过程。终于在工作之余抽出了时间写下这篇博客了,虽然是老生常谈,但是写下这些东西对于自己学习还是有很大帮助的。

    GCD(Grand Central Dispatch)

    学习GCD可以查看官方文档GCD官方文档
    弄懂GCD,首先我们该弄清楚同步异步串行并行的概念

    串行:是在同一时间执行一个线程,如果是同步所有的动作都在一个线程完成,如果是异步只需要开通一个子线程。

    并行:同一时间执行多个线程,但是这些线程都是无序的。

    同步:同一时间内只能执行一个操作,当这个操作完成后才能进行下一个操作。

    异步:多个操作同时进行,返回的先后不确定

     -(void)gcdSerial{
    dispatch_queue_t queue1 = dispatch_queue_create("qianxiao_GCD", DISPATCH_QUEUE_SERIAL);
    for (int i = 0; i < 5; i++) {
        dispatch_sync(queue1, ^{
            NSLog(@"sync:%@",[NSThread currentThread]);
        });
    }
    
    for (int i = 0; i < 5; i++) {
        dispatch_async(queue1, ^{
            NSLog(@"async:%@",[NSThread currentThread]);
            });
         }
    }
    

    打印结果为:


    轻量级交互
     -(void)gcdConcurrent{
    dispatch_queue_t queue2 = dispatch_queue_create("qianxiao_GCD", DISPATCH_QUEUE_CONCURRENT);
    
    for (int i = 0; i < 5; i++) {
        dispatch_sync(queue2, ^{
            NSLog(@"sync:%@",[NSThread currentThread]);
        });
    }
    
    for (int i = 0; i < 5; i++) {
        dispatch_async(queue2, ^{
            NSLog(@"async:%@",[NSThread currentThread]);
            });
        }
    }
    

    打印结果为:


    轻量级交互

    结论:同步dispatch_sync不管是串行还是并行,都是在主线程中实现相关操作的。而dispatch_async串行的时候只需要开启一个子线程,而在并行的时候开启不确定数目的子线程(异步并行少用,比较浪费资源)


    弄清了以上的相关功能,我们下面说下关于group创建,废话不多说先看代码

    -(void)createGCDGroup{
         dispatch_queue_t queue = dispatch_queue_create("qianxiao_group", NULL);
         dispatch_group_t group = dispatch_group_create();
         dispatch_group_async(group, queue, ^{
          NSLog(@"group_1:%@",[NSThread currentThread]);
         });
    
        dispatch_group_async(group, queue, ^{
          NSLog(@"group_2:%@",[NSThread currentThread]);
         [NSThread sleepForTimeInterval:3];
      });
      
         dispatch_group_async(group, queue, ^{
             NSLog(@"group_3:%@",[NSThread currentThread]);
            [NSThread sleepForTimeInterval:1];
      });
        dispatch_group_notify(group, queue, ^{
          NSLog(@"group_notify");
      });
    
        dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
        NSLog(@"group_wait_after:%@",[NSThread currentThread]);
    }
    

    打印结果为:


    轻量级交互

    结论:
    dispatch_group_t是创建一个组,里面异步执行dispatch_queue_t相关的任务dispatch_get_global_queue是一个全局的异步队列
    dispatch_group_notify是一个汇总的过程,他会在group里面的任务执行完成之后才会回调回来。需要注意的是dispatch_barrier_async,和dispatch_group_notify很像,dispatch_barrier_async是在该线程之前所有的操作做完之后才开始执行这个他之后线程做的操作。

    dispatch_group_wait是让上面所有的线程执行完成之后再继续执行下面的代码,但是这个会干扰主线程,让主线程也停止,所以此方法慎用。

    dispatch_suspend(), dispatch_resume()这两个方法是对一个线程挂起和恢复运行,这里的挂起保证对该函数以后的线程操作进行暂停。这两个函数一定是要成对出现的。


    dispatch_source_t是一个监视某些类型事件的对象,当这些事件被触发时,他会自动将一个block放入一个dispatch queue中执行。他和dispatch_async相比,dispatch_source_t多了一个联结的功能,这也是dispatch_source_t优势。接下来看一个小例子

    -(void)gcdSource{
        dispatch_queue_t globelQueue =  dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, globelQueue);
       dispatch_source_set_event_handler(source, ^{
         unsigned long count = dispatch_source_get_data(source);
          NSLog(@"count:%lu",count);
     });
      dispatch_resume(source);
    
     dispatch_async(globelQueue, ^{
         dispatch_source_merge_data(source, 5);
     });
    }
    

    这段代码运行结果是5; dispatch_source_t是一个挂起的程序(这里在我刚接触的时候被坑了很久),我们需要手动通过dispatch_resume启动,然后用dispatch_source_merge_data(source, 5)将结果汇总,用dispatch_source_get_data(source)得到汇总结果。

    定时器直接上代码

    -(void)gcdCountDown{
         __block int count = 30;
         dispatch_queue_t queue =   dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
         dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,queue);
         dispatch_source_set_timer(timer,dispatch_walltime(NULL, 0),1.0*NSEC_PER_SEC, 0); //1.0*NSEC_PER_SEC --> 每秒执行
         dispatch_source_set_event_handler(timer, ^{
          if (count < 0) {
                dispatch_source_cancel(timer);
           }else{
                count--;
            }
            NSLog(@"%d",count);
      });
         dispatch_resume(timer);
    }
    

    自己总结:通过写这篇博客,我理清了一些以前模棱两可的知识点,其中也参照了一些其他人的博客,毕竟是记录自己学习的过程,只要有进步一切付出都是值得的。
    如果你想了解更多的GCD知识看这篇文章

    相关文章

      网友评论

          本文标题:浅谈GCD

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