GCD里的全局队列

先说一下我们要用到的东西。
dispatch_queue_s里有个属性叫dq_serialnum。意义如名:序号。。。
overcommit:带有 overcommit 的队列表示每当有任务提交时,系统都会新开一个线程处理,这样就不会造成某个线程过载(overcommit)。
源码里一共定义了15个。

DISPATCH_CACHELINE_ALIGN
struct dispatch_queue_s _dispatch_main_q = {
    DISPATCH_GLOBAL_OBJECT_HEADER(queue_main),
#if !DISPATCH_USE_RESOLVERS
    .do_targetq = &_dispatch_root_queues[
            DISPATCH_ROOT_QUEUE_IDX_DEFAULT_QOS_OVERCOMMIT],
#endif
    .dq_state = DISPATCH_QUEUE_STATE_INIT_VALUE(1) |
            DISPATCH_QUEUE_ROLE_BASE_ANON,
    .dq_label = "com.apple.main-thread",
    .dq_atomic_flags = DQF_THREAD_BOUND | DQF_CANNOT_TRYSYNC | DQF_WIDTH(1),
    .dq_serialnum = 1,
};
DISPATCH_CACHELINE_ALIGN
struct dispatch_queue_s _dispatch_mgr_q = {
    DISPATCH_GLOBAL_OBJECT_HEADER(queue_mgr),
    .dq_state = DISPATCH_QUEUE_STATE_INIT_VALUE(1) |
            DISPATCH_QUEUE_ROLE_BASE_ANON,
    .do_targetq = &_dispatch_mgr_root_queue,
    .dq_label = "com.apple.libdispatch-manager",
    .dq_atomic_flags = DQF_WIDTH(1),
    .dq_priority = DISPATCH_PRIORITY_FLAG_MANAGER |
            DISPATCH_PRIORITY_SATURATED_OVERRIDE,
    .dq_serialnum = 2,
};
static struct dispatch_queue_s _dispatch_mgr_root_queue = {
    DISPATCH_GLOBAL_OBJECT_HEADER(queue_root),
    .dq_state = DISPATCH_ROOT_QUEUE_STATE_INIT_VALUE,
    .do_ctxt = &_dispatch_mgr_root_queue_context,
    .dq_label = "com.apple.root.libdispatch-manager",
    .dq_atomic_flags = DQF_WIDTH(DISPATCH_QUEUE_WIDTH_POOL),
    .dq_priority = DISPATCH_PRIORITY_FLAG_MANAGER |
            DISPATCH_PRIORITY_SATURATED_OVERRIDE,
    .dq_serialnum = 3,
};
DISPATCH_CACHELINE_ALIGN
struct dispatch_queue_s _dispatch_root_queues[] = {
#define _DISPATCH_ROOT_QUEUE_IDX(n, flags) \
    ((flags & DISPATCH_PRIORITY_FLAG_OVERCOMMIT) ? \
        DISPATCH_ROOT_QUEUE_IDX_##n##_QOS_OVERCOMMIT : \
        DISPATCH_ROOT_QUEUE_IDX_##n##_QOS)
#define _DISPATCH_ROOT_QUEUE_ENTRY(n, flags, ...) \
    [_DISPATCH_ROOT_QUEUE_IDX(n, flags)] = { \
        DISPATCH_GLOBAL_OBJECT_HEADER(queue_root), \
        .dq_state = DISPATCH_ROOT_QUEUE_STATE_INIT_VALUE, \
        .do_ctxt = &_dispatch_root_queue_contexts[ \
                _DISPATCH_ROOT_QUEUE_IDX(n, flags)], \
        .dq_atomic_flags = DQF_WIDTH(DISPATCH_QUEUE_WIDTH_POOL), \
        .dq_priority = _dispatch_priority_make(DISPATCH_QOS_##n, 0) | flags | \
                DISPATCH_PRIORITY_FLAG_ROOTQUEUE | \
                ((flags & DISPATCH_PRIORITY_FLAG_DEFAULTQUEUE) ? 0 : \
                DISPATCH_QOS_##n << DISPATCH_PRIORITY_OVERRIDE_SHIFT), \
        __VA_ARGS__ \
    }
    _DISPATCH_ROOT_QUEUE_ENTRY(MAINTENANCE, 0,
        .dq_label = "com.apple.root.maintenance-qos",
        .dq_serialnum = 4,
    ),
    _DISPATCH_ROOT_QUEUE_ENTRY(MAINTENANCE, DISPATCH_PRIORITY_FLAG_OVERCOMMIT,
        .dq_label = "com.apple.root.maintenance-qos.overcommit",
        .dq_serialnum = 5,
    ),
    _DISPATCH_ROOT_QUEUE_ENTRY(BACKGROUND, 0,
        .dq_label = "com.apple.root.background-qos",
        .dq_serialnum = 6,
    ),
    _DISPATCH_ROOT_QUEUE_ENTRY(BACKGROUND, DISPATCH_PRIORITY_FLAG_OVERCOMMIT,
        .dq_label = "com.apple.root.background-qos.overcommit",
        .dq_serialnum = 7,
    ),
    _DISPATCH_ROOT_QUEUE_ENTRY(UTILITY, 0,
        .dq_label = "com.apple.root.utility-qos",
        .dq_serialnum = 8,
    ),
    _DISPATCH_ROOT_QUEUE_ENTRY(UTILITY, DISPATCH_PRIORITY_FLAG_OVERCOMMIT,
        .dq_label = "com.apple.root.utility-qos.overcommit",
        .dq_serialnum = 9,
    ),
    _DISPATCH_ROOT_QUEUE_ENTRY(DEFAULT, DISPATCH_PRIORITY_FLAG_DEFAULTQUEUE,
        .dq_label = "com.apple.root.default-qos",
        .dq_serialnum = 10,
    ),
    _DISPATCH_ROOT_QUEUE_ENTRY(DEFAULT,
            DISPATCH_PRIORITY_FLAG_DEFAULTQUEUE | DISPATCH_PRIORITY_FLAG_OVERCOMMIT,
        .dq_label = "com.apple.root.default-qos.overcommit",
        .dq_serialnum = 11,
    ),
    _DISPATCH_ROOT_QUEUE_ENTRY(USER_INITIATED, 0,
        .dq_label = "com.apple.root.user-initiated-qos",
        .dq_serialnum = 12,
    ),
    _DISPATCH_ROOT_QUEUE_ENTRY(USER_INITIATED, DISPATCH_PRIORITY_FLAG_OVERCOMMIT,
        .dq_label = "com.apple.root.user-initiated-qos.overcommit",
        .dq_serialnum = 13,
    ),
    _DISPATCH_ROOT_QUEUE_ENTRY(USER_INTERACTIVE, 0,
        .dq_label = "com.apple.root.user-interactive-qos",
        .dq_serialnum = 14,
    ),
    _DISPATCH_ROOT_QUEUE_ENTRY(USER_INTERACTIVE, DISPATCH_PRIORITY_FLAG_OVERCOMMIT,
        .dq_label = "com.apple.root.user-interactive-qos.overcommit",
        .dq_serialnum = 15,
    ),
};

这些全局队列都是由系统创建的。我们只需要dispatch_get_global_queue调用就可以了。先说第一个参数。

image.png

//表是转的。如果有什么问题。求轻骂。
系统的命名很人性化。是根据OS_ENUM给的命名。

__QOS_ENUM(qos_class, unsigned int,
    QOS_CLASS_USER_INTERACTIVE
            __QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x21,
    QOS_CLASS_USER_INITIATED
            __QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x19,
    QOS_CLASS_DEFAULT
            __QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x15,
    QOS_CLASS_UTILITY
            __QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x11,
    QOS_CLASS_BACKGROUND
            __QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x09,
    QOS_CLASS_UNSPECIFIED
            __QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x00,
);

1号为主队列。2.3为管理队列。2号的do_targetq为3号。剩下的和枚举值对应。
对应的枚举。
QOS_CLASS_USER_INTERACTIVE:要求此类工作相对于系统上的其他工作以高优先级运行。指定这个QOS类是在几乎所有可用系统CPU和I/O带宽处于争用状态下运行的请求。这不是用于大型任务的节能QOS类。这个QOS类的使用应该仅限于与用户的关键交互,例如在主事件循环中处理事件、视图绘制、动画等。我们可以看出主线程对应的是QOS_CLASS_USER_INTERACTIVE。
QOS_CLASS_USER_INITIATED:这类工作的优先级要求低于关键的用户交互工作,但相对高于系统上的其他工作。这不是用于大型任务的节能QOS类。它的使用应该限制在足够短的持续时间内,这样用户在等待结果时就不太可能切换任务。典型的用户发起的工作将通过显示占位符内容或模态用户界面来指示进度。dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)获取的就是QOS_CLASS_USER_INITIATED的。
QOS_CLASS_DEFAULT:这类工作的优先级要求低于关键用户交互和用户发起的工作,但相对高于实用程序和后台任务。pthread_create()创建的线程如果没有指定QOS类的属性,则默认为QOS_CLASS_DEFAULT。qos_class是可以设置pthread优先级的。此QOS类值不打算用作工作分类,仅在传播或恢复系统提供的QOS类值时设置。我们用的比较多。
QOS_CLASS_UTILITY:这类工作的优先级要求低于关键用户交互和用户发起的工作,但相对高于低级系统维护任务。使用这个QOS类表明工作应该以一种能量和热效率的方式运行。效用工作的进展可能会或不会向用户显示,但这种工作的效果是用户可见的。对应的是我们常用的DISPATCH_QUEUE_PRIORITY_LOW。
QOS_CLASS_BACKGROUND:要求这些工作优先于其他工作运行。使用这个QOS类表明工作应该以最节能和最高效的方式运行。
4.5号我不能在app项目里使用到。希望有知道的大佬告诉我。
我们一般获取全局队列都用方法dispatch_get_global_queue。两个参数。第一个参数是优先级的。和上面对应。所以qos_class和DISPATCH_QUEUE_PRIORITY_HIGH都可以使用。第二个参数是用来控制是否overcommit.
上源码:

dispatch_queue_t
dispatch_get_global_queue(long priority, unsigned long flags)
{
    if (flags & ~(unsigned long)DISPATCH_QUEUE_OVERCOMMIT) {
        return DISPATCH_BAD_INPUT;
    }
    dispatch_qos_t qos = _dispatch_qos_from_queue_priority(priority);
#if !HAVE_PTHREAD_WORKQUEUE_QOS
    if (qos == QOS_CLASS_MAINTENANCE) {
        qos = DISPATCH_QOS_BACKGROUND;
    } else if (qos == QOS_CLASS_USER_INTERACTIVE) {
        qos = DISPATCH_QOS_USER_INITIATED;
    }
#endif
    if (qos == DISPATCH_QOS_UNSPECIFIED) {
        return DISPATCH_BAD_INPUT;
    }
    return _dispatch_get_root_queue(qos, flags & DISPATCH_QUEUE_OVERCOMMIT);
}
static inline dispatch_queue_t
_dispatch_get_root_queue(dispatch_qos_t qos, bool overcommit)
{
    if (unlikely(qos == DISPATCH_QOS_UNSPECIFIED || qos > DISPATCH_QOS_MAX)) {
        DISPATCH_CLIENT_CRASH(qos, "Corrupted priority");
    }
    return &_dispatch_root_queues[2 * (qos - 1) + overcommit];
}

这里可以看到一个判断

#define HAVE_PTHREAD_WORKQUEUE_QOS 1
#if !HAVE_PTHREAD_WORKQUEUE_QOS
    if (qos == QOS_CLASS_MAINTENANCE) {
        qos = DISPATCH_QOS_BACKGROUND;
    } else if (qos == QOS_CLASS_USER_INTERACTIVE) {
        qos = DISPATCH_QOS_USER_INITIATED;
    }

可以为我们解决一点上面的疑问。//我很好奇他这个写法。求教为什么这么写
在这里flags & DISPATCH_QUEUE_OVERCOMMIT作为一个bool传给_dispatch_get_root_queue。
enum {
DISPATCH_QUEUE_OVERCOMMIT = 0x2ull,
};
这个ull就是unsigned long long。所以我们给传一个2的话。就可以拿到有OVERCOMMIT的队列。
最后我的测试代码

    NSLog(@"high%@", dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0));
    NSLog(@"OVERCOMMIT%@", dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0));
    NSLog(@"DEFAULT%@", dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
    NSLog(@"LOW%@", dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0));
    NSLog(@"INITIATED%@", dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 2));
    NSLog(@"BACKGROUND%@", dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 2));
    NSLog(@"DEFAULT%@", dispatch_get_global_queue(QOS_CLASS_DEFAULT, 2));
    NSLog(@"UTILITY%@", dispatch_get_global_queue(QOS_CLASS_UTILITY, 2));
    NSLog(@"%@", dispatch_get_main_queue());
屏幕快照 2018-09-20 下午5.45.44.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容