iOS 多线程: 正确认识 GCD 队列类型

在面试或者跟一些有 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

也可以看出, 使用上述方式创建的 queue, 是串行队列. 所以在开头说别人说自定义 queue 是串行的, 并不一定错.

接着看第二个例子.


(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");
    });

执行结果跟例子(1)是一致的.


(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

可以看出, 不是按照顺序执行的.


你可能感兴趣的:(iOS)