YYDispatchQueuePool 是 YYKit 中用来控控制全局线程数的组件;
用法有下面两种:
// 1. 从全局的 queue pool 中获取一个 queue
dispatch_queue_t queue = YYDispatchQueueGetForQOS(NSQualityOfServiceUtility);
// 2. 创建一个新的 serial queue pool
YYDispatchQueuePool *pool = [[YYDispatchQueuePool alloc] initWithName:@"file.read" queueCount:5 qos:NSQualityOfServiceBackground];
dispatch_queue_t queue = [pool queue];
NSQualityOfService
是 iOS8.0
提供的描述优先级的枚举值, 主要有下面几种:
NSQualityOfServiceUserInteractive
NSQualityOfServiceUserInitiated
NSQualityOfServiceUtility
NSQualityOfServiceBackground
NSQualityOfServiceDefault
用来替代 GCD
中的dispatch_queue_priority_t
NSQualityOfServiceUserInteractive:最高优先级, 用于处理 UI 相关的任务
NSQualityOfServiceUserInitiated:次高优先级, 用于执行需要立即返回的任务
NSQualityOfServiceUtility:普通优先级,主要用于不需要立即返回的任务
NSQualityOfServiceBackground:后台优先级,用于处理一些用户不会感知的任务
NSQualityOfServiceDefault:默认优先级,当没有设置优先级的时候,线程默认优先级
dispatch_queue_t YYDispatchQueueGetForQOS(NSQualityOfService qos)
函数接收一个NSQualityOfService
参数同时返回一个队列;
函数内部又调用了另外一个函数static dispatch_queue_t YYDispatchContextGetQueue(YYDispatchContext *context)
;
YYDispatchContext
结构体如下:
typedef struct {
const char *name;
void **queues;
uint32_t queueCount;
int32_t counter;
} YYDispatchContext;
context
的获取通过static YYDispatchContext *YYDispatchContextGetForQOS(NSQualityOfService qos)
函数返回, 通过判断不同的qos
参数创建不同优先级的context
对象, context
对象的创建, 放在了
static YYDispatchContext *YYDispatchContextCreate(const char *name, uint32_t queueCount, NSQualityOfService qos);
函数中, 这也是整个库的核心函数, 接收3个参数: 队列名、可用核心数、优先级.
...
if ([UIDevice currentDevice].systemVersion.floatValue >= 8.0) {
dispatch_qos_class_t qosClass = NSQualityOfServiceToQOSClass(qos);
for (NSUInteger i = 0; i < queueCount; i++) {
dispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, qosClass, 0);
dispatch_queue_t queue = dispatch_queue_create(name, attr);
context->queues[i] = (__bridge_retained void *)(queue);
}
} else {
long identifier = NSQualityOfServiceToDispatchPriority(qos);
for (NSUInteger i = 0; i < queueCount; i++) {
dispatch_queue_t queue = dispatch_queue_create(name, DISPATCH_QUEUE_SERIAL);
dispatch_set_target_queue(queue, dispatch_get_global_queue(identifier, 0));
context->queues[i] = (__bridge_retained void *)(queue);
}
}
...
这里对 iOS8.0系统之前和 iOS8.0以后进行了分别处理;
iOS8.0之前:
先调用dispatch_queue_create(name, DISPATCH_QUEUE_SERIAL);
创建一个串行队列, 再调用dispatch_set_target_queue(queue, dispatch_get_global_queue(identifier, 0));
设置队列的优先级, identifier
与qos
的对应关系如下:
switch (qos) {
case NSQualityOfServiceUserInteractive: return DISPATCH_QUEUE_PRIORITY_HIGH;
case NSQualityOfServiceUserInitiated: return DISPATCH_QUEUE_PRIORITY_HIGH;
case NSQualityOfServiceUtility: return DISPATCH_QUEUE_PRIORITY_LOW;
case NSQualityOfServiceBackground: return DISPATCH_QUEUE_PRIORITY_BACKGROUND;
case NSQualityOfServiceDefault: return DISPATCH_QUEUE_PRIORITY_DEFAULT;
default: return DISPATCH_QUEUE_PRIORITY_DEFAULT;
}
iOS8.0之后:
直接通过dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, qosClass, 0);
创建一个attr
参数, 再调用dispatch_queue_create(name, attr)
创建队列; qosClass
与qos
的对应关系如下:
switch (qos) {
case NSQualityOfServiceUserInteractive: return QOS_CLASS_USER_INTERACTIVE;
case NSQualityOfServiceUserInitiated: return QOS_CLASS_USER_INITIATED;
case NSQualityOfServiceUtility: return QOS_CLASS_UTILITY;
case NSQualityOfServiceBackground: return QOS_CLASS_BACKGROUND;
case NSQualityOfServiceDefault: return QOS_CLASS_DEFAULT;
default: return QOS_CLASS_UNSPECIFIED;
}
queues
创建完成以后, 再设置queueCount
和name
, 至此context
对象创建完成.
回到YYDispatchContextGetQueue
函数:
static dispatch_queue_t YYDispatchContextGetQueue(YYDispatchContext *context) {
// 原子操作, 自增counter
uint32_t counter = (uint32_t)OSAtomicIncrement32(&context->counter);
// 每次轮询获取不同的队列
void *queue = context->queues[counter % context->queueCount];
return (__bridge dispatch_queue_t)(queue);
}
简单测试一张图片的下载可以看出: