zoukankan      html  css  js  c++  java
  • GCD多线程的使用(四)

            关于dispatch_set_target_queue和dispatch_after的使用。

            使用GCD的函数dispatch_queue_create创建的Dispatch Queue(Serial Dispatch Queue和Concurrent Dispatch Queue)使用的优先级都是默认优先级,有时根据需求可能会变更优先级,变更优先级要使用dispatch_set_target_queue函数。下面是创建一个低优先级的Serial Dispatch Queue示例:

    /**
     *  创建一个低优先级的Serial Dispatch Queue
     */
    - (void)createLowPrioritySerialDispatchQueue {
        dispatch_queue_t queue = dispatch_queue_create("com.hxp.queue", DISPATCH_QUEUE_SERIAL);  //此时的优先级为默认优先级
        dispatch_queue_t targetQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0); //创建一个低优先级的目标Global Dispatch Queue
        dispatch_set_target_queue(queue, targetQueue);  //更改优先级为目标Dispatch Queue的优先级
    }

            dispatch_set_target_queue函数的第一个参数是需要变更优先级的Dispatch Queue,第二个参数是指定要使用的执行优先级相同优先级的Global Dispatch Queue,即目标Dispatch Queue。

            另外,dispatch_set_target_queue函数还有指定执行顺序的功能呢,先看代码和输出结果:

        dispatch_queue_t queue0 = dispatch_queue_create("com.hxp.queue0", DISPATCH_QUEUE_SERIAL);
        dispatch_queue_t queue1 = dispatch_queue_create("com.hxp.queue1", DISPATCH_QUEUE_SERIAL);
        dispatch_queue_t queue2 = dispatch_queue_create("com.hxp.queue2", DISPATCH_QUEUE_SERIAL);
        dispatch_queue_t queue3 = dispatch_queue_create("com.hxp.queue3", DISPATCH_QUEUE_SERIAL);
        dispatch_queue_t queue4 = dispatch_queue_create("com.hxp.queue4", DISPATCH_QUEUE_SERIAL);
        
        
        dispatch_async(queue0, ^{
            NSLog(@"%@:queue0", [NSThread currentThread]);
        });
        dispatch_async(queue1, ^{
            NSLog(@"%@:queue1", [NSThread currentThread]);
        });
        dispatch_async(queue2, ^{
            NSLog(@"%@:queue2", [NSThread currentThread]);
        });
        dispatch_async(queue3, ^{
            NSLog(@"%@:queue3", [NSThread currentThread]);
        });
        dispatch_async(queue4, ^{
            NSLog(@"%@:queue4", [NSThread currentThread]);
        });

            正常的输出结果应该是顺序杂乱无章,并发执行:

    2015-06-19 07:01:12.885 GCD_Study[23054:3603] {name = (null), num = 6}:queue4
    2015-06-19 07:01:12.885 GCD_Study[23054:1303] {name = (null), num = 2}:queue0
    2015-06-19 07:01:12.885 GCD_Study[23054:3403] {name = (null), num = 5}:queue2
    2015-06-19 07:01:12.885 GCD_Study[23054:3503] {name = (null), num = 3}:queue3
    2015-06-19 07:01:12.885 GCD_Study[23054:3107] {name = (null), num = 4}:queue1

            然后使用dispatch_set_target_queue函数指定优先级后:

        dispatch_queue_t queue0 = dispatch_queue_create("com.hxp.queue0", DISPATCH_QUEUE_SERIAL);
        dispatch_queue_t queue1 = dispatch_queue_create("com.hxp.queue1", DISPATCH_QUEUE_SERIAL);
        dispatch_queue_t queue2 = dispatch_queue_create("com.hxp.queue2", DISPATCH_QUEUE_SERIAL);
        dispatch_queue_t queue3 = dispatch_queue_create("com.hxp.queue3", DISPATCH_QUEUE_SERIAL);
        dispatch_queue_t queue4 = dispatch_queue_create("com.hxp.queue4", DISPATCH_QUEUE_SERIAL);
        
        dispatch_set_target_queue(queue1, queue0);
        dispatch_set_target_queue(queue2, queue0);
        dispatch_set_target_queue(queue3, queue0);
        dispatch_set_target_queue(queue4, queue0);
        
        dispatch_async(queue0, ^{
            NSLog(@"%@:queue0", [NSThread currentThread]);
        });
        dispatch_async(queue1, ^{
            NSLog(@"%@:queue1", [NSThread currentThread]);
        });
        dispatch_async(queue2, ^{
            NSLog(@"%@:queue2", [NSThread currentThread]);
        });
        dispatch_async(queue3, ^{
            NSLog(@"%@:queue3", [NSThread currentThread]);
        });
        dispatch_async(queue4, ^{
            NSLog(@"%@:queue4", [NSThread currentThread]);
        });

            这次是使用dispatch_set_target_queue函数指定目标为一个Serial Dispatch Queue,输出结果:

    2015-06-19 07:16:11.244 GCD_Study[23239:1303] {name = (null), num = 2}:queue0
    2015-06-19 07:16:11.246 GCD_Study[23239:1303] {name = (null), num = 2}:queue1
    2015-06-19 07:16:11.247 GCD_Study[23239:1303] {name = (null), num = 2}:queue2
    2015-06-19 07:16:11.248 GCD_Study[23239:1303] {name = (null), num = 2}:queue3
    2015-06-19 07:16:11.250 GCD_Study[23239:1303] {name = (null), num = 2}:queue4

            原本并行执行的多个Serial Dispatch Queue变成了串行执行。在必须将不可并行执行的处理追加到多个Serial Dispatch Queue中时,如果用dispatch_set_target_queue函数将目标指定为某一个Serial Dispatch Queue,即可防止处理并行执行。

            想象这样一个场景:我想在几秒后执行某一个操作。这样的场景就需要用到dispatch_after函数了。下面的代码是在2秒后输出一个字符串:

    - (void)dispatchAfter {
        dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 2ull * NSEC_PER_SEC);
        dispatch_queue_t queue = dispatch_get_main_queue();
        NSLog(@"Now");
        dispatch_after(time, queue, ^{
            NSLog(@"after 2sec");
        });
    }

            输出结果:

    2015-06-19 07:46:20.182 GCD_Study[23269:607] Now
    2015-06-19 07:46:22.183 GCD_Study[23269:607] after 2sec

            虽然有误差,但大概也是2秒后了。因为dispatch_after函数并不是在指定的时间后执行处理,而是在指定的时间追加处理到Dispatch Queue。上面那段代码意思是在2秒后将执行任务的Block用dispatch_async追加到Main Dispatch Queue中。

            下面说一下dispatch_after函数的三个参数。第一个参数是指定时间用的dispatch_time_t类型的值,该值用dispatch_time函数或者dispatch_walltime函数获得。dispatch_time函数获取的是从第一个参数指定的时间开始,到第二个参数指定的毫微秒单位时间后的时间。上面的代码中第一个参数用的DISPATCH_TIME_NOW,表示从现在开始,第二个参数是2ull*NSEC_PER_SEC,表示延迟2秒,合起来就是从现在开始2秒后将Block追加到Main Dispatch Queue中。

            数值和NSEC_PER_SEC的乘积得到单位为毫微秒的数值。有以下取值

    #define NSEC_PER_USEC    1000ull        /* nanoseconds per microsecond */
    #define USEC_PER_SEC    1000000ull    /* microseconds per second */
    #define NSEC_PER_SEC    1000000000ull    /* nanoseconds per second */
    #define NSEC_PER_MSEC    1000000ull    /* nanoseconds per millisecond */

            NSEC_PER_USEC:1000纳秒/1微秒

            USEC_PER_SEC  :1000000微秒/1秒

            NSEC_PER_SEC  :1000000000纳秒/1秒

            NSEC_PER_MSEC:1000000纳秒/1毫秒

            ull是C语言中得数值字面量,是显示表明类型时使用的字符串,表示unsigned long long。

  • 相关阅读:
    listview 加载性能优化 viewholder
    eclipse使用有感
    android常见的错误
    填充父窗体布局问题
    setTag()/getTag()
    自己动手实现自旋锁
    新手学信息检索6:谈谈二值独立模型
    自己动手编译、运行Java程序
    新手学信息检索5:正确率召回率与搜索引擎的评价
    新手学信息检索4:向量空间模型与相似度计算
  • 原文地址:https://www.cnblogs.com/arthas/p/4658414.html
Copyright © 2011-2022 走看看