
队列
在GCD中包含了四种队列 : 主队列、 全局队列、 管理队列、自定义队列。这里我们一一来看,其中的实现逻辑。
自定义队列
队列底层使用dispatch_queue_create进行创建
1 | dispatch_queue_t |
全局队列 - dispatch_get_global_queue
1 | dispatch_queue_global_t |
这里我们可以看到全局队列最终调用的是_dispatch_get_root_queue
1 | DISPATCH_ALWAYS_INLINE DISPATCH_CONST |
实际上_dispatch_root_queuess是一个系统硬编码的队列数组
1 | struct dispatch_queue_global_s _dispatch_root_queues[] = { |
主队列
1 | struct dispatch_queue_static_s _dispatch_main_q = { |
管理队列
1 | struct dispatch_queue_global_s _dispatch_mgr_root_queue = { |
可以看到,无论是主队列,管理队列,还是自定义队列,都使用root queue作为target queue
Target Queue
Darget queue 是队列任务最终执行的地方。但是全局队列没有设置target queue (do_targetq)。同时值得注意的是,targetQueue才是提交的block执行的关键
The target queue determines whether the block will be invoked serially or concurrently with respect to other blocks submitted to that same queue.Serial queues are processed concurrently with respect to each other.
QOS
在设置队列优先级的时候会涉及到QOS的设置。QOS是自iOS8后新引入的特性。主要包含以下五种:
NSQualityOfServiceUserInteractive
用户交互相关,通常和UI相关。NSQualityOfServiceUserInitiated
由用户发起且需要立即完成的任务NSQualityOfServiceUtility
需要花费一些时间,不是马上需要结果的任务NSQualityOfServiceBackground
后台任务NSQualityOfServiceDefault
默认优先级,介于NSQualityOfServiceUserInteractive和NSQualityOfServiceUtility之间,在没有QOS信息时默认使用
队列优先级和QOS类之间的映射关系如下1
2
3
4DISPATCH_QUEUE_PRIORITY_HIGH: QOS_CLASS_USER_INITIATED
DISPATCH_QUEUE_PRIORITY_DEFAULT: QOS_CLASS_DEFAULT
DISPATCH_QUEUE_PRIORITY_LOW: QOS_CLASS_UTILITY
DISPATCH_QUEUE_PRIORITY_BACKGROUND: QOS_CLASS_BACKGROUND
Overcommit
overcommit 参数表示队列在执行blokc时,无论多忙都会新开一个线程
The queue will create a new thread for invoking blocks, regardless of how
busy the computer is.
在root queue我们也可以看到overcommit的身影。值得注意的是全局队列和自定义并发队列是非overcommit的,而主队列和自定义串行队列的都是overcommit的。当我们使用dispatch_async提交任务到串行队列,由于串行队列一般是overcommit的,所以会创建一个新的线程,而并发队列是非overcommit的,所以不会创建新的线程,而是从底层的线程池中获取。
即便如此,队列在同步执行任务时是不会创建新的线程的,所有的任务都会在当前的线程中执行,且会阻塞线程。dispatch_sync底层使用信号量来实现串行
任务提交
我们提交的block任务,经过GCD底层封装之后,被存储于队列的链表中,符合FIFO原则。
只有提交到主队列的任务是在主线程中执行,因为其内部线程是和队列绑定的。主队列的任务由Runloop处理,但是分发到其他队列的任务由底层的线程池处理
API深入
dispatch_sync
1 | DISPATCH_NOINLINE |
dispatch_async
1 | void |