GCD使用

作者: 暖光照 | 来源:发表于2016-10-08 18:10 被阅读0次

    名词

    • 串行(Serial)与 并发(Concurrent)
      任务串行,意味着在同一时间,有且只有一个任务被执行,即一个任务执行完毕之后再执行下一个任务。
      任务并发,意味着在同一时间,有多个任务被执行。

    • 同步(Synchronous)与 异步 (Asynchronous)
      同步,意味着在当前线程中执行任务,不具备开启新的线程的能力。

    异步,在新的线程中执行任务,具备开启新的线程的能力。

    在 GCD 中,这些术语描述当一个函数相对于另一个任务完成,此任务是该函数要求 GCD 执行的。一个同步函数只在完成了它预定的任务后才返回(阻塞当前Queue,先执行传入的Queue)

    一个异步函数,刚好相反,会立即返回,预定的任务会完成但不会等它完成。因此,一个异步函数不会阻塞当前线程去执行下一个函数。

    GCD获取的队列

    //得到运行在主线程的mainQueue
    dispatch_queue_t mainQueue=dispatch_get_main_queue();
    
    //得到全局队列(全局的并行队列)
    dispatch_queue_t globalQueue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    //创建一个串行队列
    dispatch_queue_t serialQueue=dispatch_queue_create("queueName", DISPATCH_QUEUE_SERIAL);
    
    //创建一个并行队列
    dispatch_queue_t concurrentQueue=dispatch_queue_create("queueName", DISPATCH_QUEUE_CONCURRENT);
    

    GCD的使用

    基本使用
    //同步执行
    dispatch_sync(queue, ^{
        // do something
    });
    
    //异步执行
    dispatch_async(queue, ^{
        // do something
    });
    
    // 一次性执行:
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        // do something
    });
    
    // 延迟2秒执行:
    double seconds = 2.0;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, seconds * NSEC_PER_SEC);
    dispatch_after(popTime, queue, ^(void){
        // do something
    });
    
    使用group
        // 创建group
    dispatch_group_t group=dispatch_group_create();
    dispatch_group_async(group, queue, ^{
        //任务一
    });
    dispatch_group_async(group, queue, ^{
        //任务二
    });
    dispatch_group_notify(group, queue, ^{
        //任务都结束调用
    });
    
    单例
     + (Manager *)sharedManager
    {
        static Manager *sharedManagerInstance = nil;
        static dispatch_once_t onct;
        dispatch_once(&onct, ^{
        sharedManagerInstance = [[self alloc] init];
        });
        return sharedManagerInstance;
    }
    

    串行并行队列与同步异步执行的各种组合

    1、 异步函数 + 并行队列
    可以新建线程,各线程也是并发执行的。
    结论:在队列中的任务“在多个线程并发”执行
    2、 同步函数+并发队列
    因为是同步函数,所以不新建线程,只要是同步函数,就不会新建线程。
    并发队列与否,并不影响同步函数的创建,因为本身就不能多创建线程,也就不存在并发。
    结论:在队列中的任务“one by one”执行
    3、异步函数+串行队列
    这个搭配可以新建线程,但是因为是串行队列,所以实际上也只是开了一条新线程,做完一个,再做另一个。
    结论:在队列中的任务“在新线程one by one”执行
    4、同步函数+串行队列
    这样既不会开新线程,也是串行执行的。
    结论:在队列中的任务“one by one”执行

    注意:

    当串行queue中调用dispatch_sync传入的还是当前queue,会造成死锁。
    例如:

     dispatch_async(serialQueue1, ^{
        //serialQueue1队列中调用dispatch_sync传入的还是serialQueue1.
        //dispatch_async创建的新线程会死锁
        dispatch_sync(serialQueue1, ^{
            NSLog(@"1554654-----%@",[NSThread currentThread]);
        });
    });           
    

    或:

      //主线程中调用会死锁
       dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"1-----%@",[NSThread currentThread]);
     });
    

    原因:
    dispatch_sync会阻塞当前queue等待传入的queue执行完返回才会继续。而传入的还是当前queue。需要执行的block被放到传入queue的队尾等待执行。而queue还在等待dispatch_sync函数返回。block永远不会执行,dispatch_sync永远不会返回,造成死锁

    相关文章

      网友评论

          本文标题:GCD使用

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