GCD小结

610 阅读4分钟

1 线程、队列、RunLoop

1.1 线程与队列

  1. 线程是执行者,队列是等待执行的任务队列。

  2. GCD是程序员告诉队列中的任务通过什么方式,在哪个或哪些队列执行。

1.2 GCD与RunLoop

  1. 对于主线程中的task queue,相当于加入到了main RunLoop的dispatch block

  2. 对于并发队列中的task,我的理解是,

相当于加入到了子线程的任务队列中

这些并发队列,是使用的GCD底层线程池来执行的,但是这些线程中并没有RunLoop(iOS13模拟器中用currentRunLoop测试,发现RunLoop中没有任何observer、source、timer来保活),GCD的保活应该是通过直接引用线程对象来处理的,并且是弹性的,见第9节。

2 queue

2.1 自定义队列

串行队列:队列中的任务只会顺序执行

dispatch_queue_t q = dispatch_queue_create("...", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t q = dispatch_queue_create("...", NULL);

并行队列: 队列中的任务通常会并发执行

dispatch_queue_t q = dispatch_queue_create("......",DISPATCH_QUEUE_CONCURRENT);

2.2 系统标准队列

全局队列:是系统的,直接GET。并行

dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

主队列:每一个应用程序对应唯一主队列,直接GET。串行 主队列只会运行在主线程上,使用主队列更新UI。 主线程可以执行其他队列的任务。

dispatch_queue_t q = dispatch_get_main_queue();

3 同步、异步,针对的是向前线程

dispatch_sync(_queue, ^() {
    //...
}

4 dispatch_group

Case: 有a、b、c、d 4个异步请求,如何判断a、b、c、d都完成执行?如果需要a、b、c、d顺序执行,该如何实现?

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, ^{ /*任务a */ });
dispatch_group_async(group, queue, ^{ /*任务b */ });
dispatch_group_async(group, queue, ^{ /*任务c */ });
dispatch_group_async(group, queue, ^{ /*任务d */ });

//先提交,再用notify或者wait
dispatch_group_notify(group,dispatch_get_main_queue(), ^{
// 在a、b、c、d异步执行完成后,会回调这里
});

//dispatch_group_wait(_loggingGroup, DISPATCH_TIME_FOREVER);

顺序执行,queue用串行队列。

5 dispatch_barrier_async

  1. 在同一个queue(哪怕是并行队列)里面,执行顺序:barrier之前的任务、barrier任务、barrier之后的任务。
  2. 只在自定义队列上有效,在系统标准队列上,效果等同于dispatch_sync。
//不使用barrier时
dispatch_queue_t queue = dispatch_queue_create("queue_name", DISPATCH_QUEUE_CONCURRENT);

    dispatch_async(queue, ^{
        NSLog(@"----耗时任务1-----%@", [NSThread currentThread]);
    });

    dispatch_async(queue, ^{
        NSLog(@"----耗时任务2-----%@", [NSThread currentThread]);
    });

    dispatch_async(queue, ^{
        NSLog(@"----耗时任务3-----%@", [NSThread currentThread]);
    });

    dispatch_async(queue, ^{
        NSLog(@"----耗时任务4-----%@", [NSThread currentThread]);
    });

dispatch_queue_t queue = dispatch_queue_create("queue_name", DISPATCH_QUEUE_CONCURRENT);

    dispatch_async(queue, ^{
        NSLog(@"----耗时任务1-----%@", [NSThread currentThread]);
    });

    dispatch_async(queue, ^{
        NSLog(@"----耗时任务2-----%@", [NSThread currentThread]);
    });

    dispatch_async(queue, ^{
        NSLog(@"----耗时任务3-----%@", [NSThread currentThread]);
    });

    dispatch_barrier_async(queue, ^{
        NSLog(@"----barrier-----%@", [NSThread currentThread]);
    });

    dispatch_async(queue, ^{
        NSLog(@"----耗时任务4-----%@", [NSThread currentThread]);
    });

 dispatch_async(queue, ^{
        NSLog(@"----耗时任务5-----%@", [NSThread currentThread]);
    });

6 dispatch_time

比NSTimer更精准

dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC));

//dispatch_time的第二个参数的单位是纳秒

#define NSEC_PER_SEC 1000000000ull //每秒的纳秒数

dispatch_resume(timer)//激活timer
dispatch_source_cancel(timer)//取消timer

7 任务取消

两种方法,其中第二种方法只能停止单个任务,不能取消整个队列的任务。

只能取消未开始的任务。

  1. 利用外部变量

  2. 利用dispatch_block_create、dispatch_block_cancel

8 对比NSOperationQueue

8.1 NSOperationQueue与GCD之间的关系

GCD是纯C语言的API 。

NSOperationQueue是基于GCD的OC的封装。

8.2 两者的不同

  1. GCD只支持FIFO队列,NSOperationQueue可以重新设置优先级,最大并发数。

  2. NSOperationQueue可是方便设置operation之间的依赖关系,GCD则需要很多代码。

  3. NSOperationQueue支持KVO,即可以观察任务的执行状态,正在执行(isExecuted),是否结束(isFinished),是否取消(isCanceled)。

8.3 结论

  1. GCD更接近底层,而NSOperationQueue则更高级抽象。

  2. GCD速度更快。

  3. 任务之间的依赖关系。GCD需要自己写更多的代码来实现,而NSOperationQueue已经内建了这些支持。

9 底层原理

  1. 串行并行,同步异步

GCD分串行队列和并行队列(针对队列),执行分为同步和异步(针对线程)

  1. 同步异步决定是否开辟新线程,串行并行决定同时在几个线程执行

  1. 底层原理

GCD底层有一个线程池,通过线程池来管理线程的重用和销毁,系统会自己维护这个线程池。

从这个角度讲,这些线程应该是有RunLoop的。

a. GCD的层次比线程高,其底层是利用多线程来实现的。

b. GCD比之thread更加简单易用。由于GCD基于工作单元(work unit)而非像thread那样基于运算,所以GCD可以控制诸如等待任务结束、监视文件描述符、周期执行代码以及工作挂起等任务。

c. GCD自动根据系统负载(比例内存使用情况、CPU个数)来增减线程数量

ps:有价值的文章,深入理解 GCDGCD底层实现理解