GCD - 队列管理

dispatch_queue_t

队列对应一个dispatch_queue_t对象即:

dispatch_queue_t queue;

类似普通OC对象,可以用dispatch_retain()和dispatch_release()对其进行内存管理,当一个任务加入到一个queue中的时候,任务会retain这个queue,直到任务执行完成才会release。iOS6之后dispatch对象已经支持ARC,所以在ARC工程之下,我们可以不用担心他的内存。

一般情况下只需要用strong申明一个dispatch的属性。

@property (nonatomic, strong) dispatch_queue_t queue;

如果你是写一个framework,framework的使用者的SDK有可能还是古董级的iOS6之前。那么你需要根据OS_OBJECT_USE_OBJC做一个判断是使用strong还是assign。(一般github上的优秀第三方库都会这么做)

#if OS_OBJECT_USE_OBJC
@property (nonatomic, strong) dispatch_queue_t queue;
#else
@property (nonatomic, assign) dispatch_queue_t queue;
#endif

<li><h4>获取主线程队列<h4></li>

主线程是我们最常用的线程,获取主线程队列的方法很简单:

dispatch_queue_t mainQueue;
mainQueue = dispatch_get_main_queue();

假设要在主线程更新UI:

dispatch_async(dispatch_get_main_queue(), ^{
    [self updateUI];
});

执行加入到主线程队列的block,App会调用dispatch_main(), NSApplicationMain(),或者在主线程使用CFRunLoop。

<li><h4>获取全局队列<h4></li>

除了主线程队列,GCD提供了几个全局队列,可以直接获取使用

dispatch_queue_t dispatch_get_global_queue(long identifier, unsigned long flags);

dispatch_get_global_queue方法获取的全局队列都是并行队列,并且队列不能被修改,也就是说对全局队列调用dispatch_suspend(), dispatch_resume(), dispatch_set_context()等方法无效。

全局队列对于程序来说是全局的,retain和release会被全局队列忽略。所以,我们不需要存储这些队列的引用数。

identifier: 用以标识队列优先级,推荐用qos_class枚举作为参数,也可以使用dispatch_queue_priority_t

flags: 预留字段,传入任何非0的值都可能导致返回NULL

代码示例:

dispatch_queue_t aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

全局队列的四种类型

DISPATCH_QUEUE_PRIORITY_HIGH : 最高优先级,交互级别。使用这个优先级会占用几乎所有的系统CUP和I/O带宽,仅限用于交互的UI操作,比如处理点击事件,绘制图像到屏幕上,动画等

DISPATCH_QUEUE_PRIORITY_DEFAULT : 默认优先级,当没有设置优先级的时候,线程默认优先级。一般情况下用的都是这个优先级

DISPATCH_QUEUE_PRIORITY_LOW : 普通优先级,主要用于不需要立即返回的任务

DISPATCH_QUEUE_PRIORITY_BACKGROUND : 后台优先级,用于用户几乎不感知的任务。它会等待所有比它级别高的队列中的任务执行完或CPU空闲的时候才会执行自己的任务。例如磁盘的读写操作非常耗时,如果我们不需要立即获取到磁盘的数据,我们可以把读写任务放到后台队列中,这样读写任务只会在恰当的时候去执行而不会影响需要更改优先级的其他任务,整个程序也会更加有效率。

由于NULL等于0,也就是DISPATCH_QUEUE_PRIORITY_DEFAULT,所以将0或者NULL传入作为参数返回的是默认优先级:

dispatch_get_global_queue(NULL, NULL)

<li><h4>创建串行队列&并发队列<h4></li>
当无法获取到理想的队列时,我们可以自己创建队列:

dispatch_queue_t dispatch_queue_create(const char *label, dispatch_queue_attr_t attr);

label: 队列的名称,调试的时候可以区分其他的队列

attr: 队列的属性,dispatch_queue_attr_t类型。用以标识队列串行,并行,以及优先级等信息

attr参数有三种传值方式:

// 串行
#define DISPATCH_QUEUE_SERIAL NULL
 
// 并行
#define DISPATCH_QUEUE_CONCURRENT \
        DISPATCH_GLOBAL_OBJECT(dispatch_queue_attr_t, \
        _dispatch_queue_attr_concurrent)
         
// 自定义属性值
dispatch_queue_attr_t dispatch_queue_attr_make_with_qos_class(dispatch_queue_attr_t attr, dispatch_qos_class_t qos_class, int relative_priority);

DISPATCH_QUEUE_SERIAL 或者 NULL,表示创建串行队列,优先级为目标队列优先级。

DISPATCH_QUEUE_CONCURRENT,表示创建并行队列,优先级也为目标队列优先级。

另外, 自定义属性值
dispatch_queue_attr_make_with_qos_class函数可以创建带有优先级的dispatch_queue_attr_t对象。通过这个对象可以自定义queue的优先级。

attr: 传入DISPATCH_QUEUE_SERIAL、NULL或DISPATCH_QUEUE_CONCURRENT,表示串行或者并行

qos_class: 传入qos_class枚举,表示优先级级别

relative_priority: 相对于qos_class的相对优先级,qos_class用于区分大的优先级级别,relative_priority表示大级别下的小级别。relative_priority必须大于QOS_MIN_RELATIVE_PRIORITY小于0,否则将返回NULL。从GCD源码中可以查到QOS_MIN_RELATIVE_PRIORITY等于-15

使用dispatch_queue_attr_make_with_qos_class创建队列时,需要注意,非法的参数可能导致dispatch_queue_attr_make_with_qos_class返回NULL,dispatch_queue_create传入NULL会创建出串行队列。写代码过程中需要确保这是否是预期的结果

常用创建队列代码示例:

  //串行队列
   dispatch_queue_t serialQueue;
   serialQueue = dispatch_queue_create("com.example.SerialQueue", NULL);

  //并发队列
  dispatch_queue_t concurrentQueue;
   concurrentQueue = dispatch_queue_create("com.example.ConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容