在面试或者跟一些有 ios 编程经验的人聊到关于 GCD 的队列类型的问题.
很多人说自定义的 queue 是串行队列.
这种说法在一定程度上是不对的, 下面具体再说.
今天跟大家聊聊 GCD 中的队列类型问题.
------------------------------------------------------------------------------------------------
目前, GCD 有三种队列类型.
* main queue: 主队列.
* global queue: 全局队列.
* custom queue: 自定义队列.
------------------------------------------------------------------------------------------------
下面具体聊聊吧!
1. main queue
* 获取方式
dispatch_get_main_queue()
* 细说
一般使用 main queue, 都是在该线程中操作 UI 相关的.
也就是说, 在 main queue 中执行的任务会在主线程中执行.
主线程只有一个, main queue是与主线程相关的,所以main queue 是串行队列.
2. global queue
* 获取方式
dispatch_get_global_queue(long identifier, unsigned long flags);
第二个参数是保留参数.一般会设置为 0.
可以参考官方注释
/*!
* @function dispatch_get_global_queue
*
* @abstract
* Returns a well-known global concurrent queue of a given quality of service
* class.
*
* @discussion
* The well-known global concurrent queues may not be modified. Calls to
* dispatch_suspend(), dispatch_resume(), dispatch_set_context(), etc., will
* have no effect when used with queues returned by this function.
*
* @param identifier
* A quality of service class defined in qos_class_t or a priority defined in
* dispatch_queue_priority_t.
*
* It is recommended to use quality of service class values to identify the
* well-known global concurrent queues:
* - QOS_CLASS_USER_INTERACTIVE
* - QOS_CLASS_USER_INITIATED
* - QOS_CLASS_DEFAULT
* - QOS_CLASS_UTILITY
* - QOS_CLASS_BACKGROUND
*
* The global concurrent queues may still be identified by their priority,
* which map to the following QOS classes:
* - DISPATCH_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
*
* @param flags
* Reserved for future use. Passing any value other than zero may result in
* a NULL return value.
*
* @result
* Returns the requested global queue or NULL if the requested global queue
* does not exist.
*/
global queue 是并发队列.可以设置其优先级.
3. Custom queue
* 获取方式
dispatch_queue_create(const char *label, dispatch_queue_attr_t attr);
这些队列是可以是串行的, 也可以是并行的。默认是串行的.
串行队列可以保证任务是串行的, 保证了执行顺序.类似锁机制.
* 例子
(1). 默认是串行队列.
// 自定义队列(NULL, 默认是串行队列)
dispatch_queue_t queue = dispatch_queue_create("gcd.mark", NULL);
NSLog(@"create custom queue completed.");
dispatch_async(queue, ^{
// 模拟耗时
[NSThread sleepForTimeInterval:2];
NSLog(@"Run First Task");
});
dispatch_async(queue, ^{
NSLog(@"Run Sencond Task");
});
dispatch_async(queue, ^{
NSLog(@"Run Third Task");
});
// 执行结果
2015-10-31 23:33:14.267 dsds[87226:1308349] create custom queue completed.
2015-10-31 23:33:16.269 dsds[87226:1308582] Run First Task
2015-10-31 23:33:16.270 dsds[87226:1308582] Run Sencond Task
2015-10-31 23:33:16.270 dsds[87226:1308582] Run Third Task
接着看第二个例子.
(2). 指定为串行
// 指定为串行队列
dispatch_queue_t queue = dispatch_queue_create("gcd.mark", DISPATCH_QUEUE_SERIAL);
NSLog(@"create custom queue completed.");
dispatch_async(queue, ^{
// 模拟耗时
[NSThread sleepForTimeInterval:2];
NSLog(@"Run First Task");
});
dispatch_async(queue, ^{
NSLog(@"Run Sencond Task");
});
dispatch_async(queue, ^{
NSLog(@"Run Third Task");
});
(3). 指定为并行
// 指定为并行队列
dispatch_queue_t queue = dispatch_queue_create("gcd.mark", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"create custom queue completed.");
dispatch_async(queue, ^{
// 模拟耗时
[NSThread sleepForTimeInterval:2];
NSLog(@"Run First Task");
});
dispatch_async(queue, ^{
NSLog(@"Run Sencond Task");
});
dispatch_async(queue, ^{
NSLog(@"Run Third Task");
});
2015-10-31 23:37:06.052 dsds[87270:1310892] create custom queue completed.
2015-10-31 23:37:06.052 dsds[87270:1310988] Run Sencond Task
2015-10-31 23:37:06.052 dsds[87270:1311060] Run Third Task
2015-10-31 23:37:08.057 dsds[87270:1311055] Run First Task