多线程编程之GCD(二)

作者: kevinLY | 来源:发表于2017-02-26 15:22 被阅读263次

    承接上一篇:多线程编程之GCD(一)

    三、系统Dispatch_Queue

    GCD提供了两个系统的Queue:1、Main Dispatch Queue;2、Global Dispatch Queue

    Main Dispatch Queue:是在主线程中执行的Dispatch Queue,因为主线程只有一个,所以Main Dispatch Queue就是Serial Dispatch Queue;像一些界面刷新等必须在主线程下执行的操作,可以把任务追加到Main Dispatch Queue中,类似于[NSObject performSelectorOnMainThread:];

    Global Dispatch Queue:是一个Concurrent Dispatch Queue;
    Global Dispatch Queue 有四个执行优先级:DISPATCH_QUEUE_PRIORITY_HIGH、DISPATCH_QUEUE_PRIORITY_DEFAULT、DISPATCH_QUEUE_PRIORITY_LOW、DISPATCH_QUEUE_PRIORITY_BACKGROUND

    参照官方API
    /*!
     *  @function dispatch_get_global_queue
     *  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.
     */
    __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_4_0)
    DISPATCH_EXPORT DISPATCH_CONST DISPATCH_WARN_RESULT DISPATCH_NOTHROW
    dispatch_queue_t
    dispatch_get_global_queue(long identifier, unsigned long flags);
    
    获取Main Dispatch Queue
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    获取Global Dispatch Queue
    dispatch_queue_t highQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
    

    注:通过 dispatch_queue_t queue = dispatch_queue_create("com.qmf", DISPATCH_QUEUE_CONCURRENT||DISPATCH_QUEUE_Serial);创建的queue的优先级和dispatch_queue_t defaultQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);相同;

    四、dispatch_set_target_queue

    通过 dispatch_queue_t queue = dispatch_queue_create("com.qmf", DISPATCH_QUEUE_CONCURRENT||DISPATCH_QUEUE_Serial);创建的queue的优先级和dispatch_queue_t defaultQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);相同。
    当我们想改变自己创建的Dispatch Queue的优先级的时候可以使用dispatch_set_target_queue

    dispatch_set_target_queue有两个作用:
    一、变更用户生成的Dispatch Queue的优先级

    代码演示:

    //设置优先级
    dispatch_queue_t myqueue = dispatch_queue_create("com.qmf", NULL);
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
    // 第一个参数为要设置优先级的queue,第二个参数是参照物,既将第一个queue的优先级和第二个queue的优先级设置一样。Dispatch Queue
    dispatch_set_target_queue(myqueue, globalQueue);
    

    二、设置Dispatch Queue的执行层次

    首先,我们需要阐述一下生成多个Serial DisPatch Queue时的注意事项Serial DisPatch Queue是一个串行队列,只能同时执行1个追加处理(即任务),当用Dispatch_queue_create函数生成多个Serial DisPatch Queue时,每个Serial DisPatch Queue均获得一个线程,即多个Serial DisPatch Queue可并发执行,同时处理添加到各个Serial DisPatch Queue中的任务,但要注意如果过多地使用多线程,就会消耗大量内存,引起大量的上下文切换,大幅度降低系统的响应性能,所以我们只在为了避免多个线程更新相同资源导致数据竞争时,使用Serial DisPatch Queue

    第一种情况:使用dispatch_set_target_queue(queue1, queue2)实现队列的动态调度

    - (void)testTargetQueue2 {
        //创建一个串行队列queue1
        dispatch_queue_t queue1 = dispatch_queue_create("test.1", DISPATCH_QUEUE_SERIAL);
        //创建一个串行队列queue2
        dispatch_queue_t queue2 = dispatch_queue_create("test.2", DISPATCH_QUEUE_SERIAL);
        
        //使用dispatch_set_target_queue()实现队列的动态调度管理
        dispatch_set_target_queue(queue1, queue2);
        
        
        /*
         
         <*>dispatch_set_target_queue(Dispatch Queue1, Dispatch Queue2);
         那么dispatchA上还未运行的block会在dispatchB上运行。这时如果暂停dispatchA运行:
         
         <*>dispatch_suspend(dispatchA);
         这时则只会暂停dispatchA上原来的block的执行,dispatchB的block则不受影响。而如果暂停dispatchB的运行,则会暂停dispatchA的运行。
         
         这里只简单举个例子,说明dispatch队列运行的灵活性,在实际应用中你会逐步发掘出它的潜力。
         
         dispatch队列不支持cancel(取消),没有实现dispatch_cancel()函数,不像NSOperationQueue,不得不说这是个小小的缺憾
         
         */
        
        dispatch_async(queue1, ^{
            for (NSInteger i = 0; i < 10; i++) {
                NSLog(@"queue1:%@, %ld", [NSThread currentThread], i);
                [NSThread sleepForTimeInterval:0.5];
                if (i == 5) {
                    dispatch_suspend(queue1);
                }
            }
        });
        
        dispatch_async(queue1, ^{
            for (NSInteger i = 0; i < 100; i++) {
                NSLog(@"queue1:%@, %ld", [NSThread currentThread], i);
            }
            
        });
        
        dispatch_async(queue2, ^{
            for (NSInteger i = 0; i < 100; i++) {
                NSLog(@"queue2:%@, %ld", [NSThread currentThread], i);
            }
        });
        
    }
    

    第二种情况:使用dispatch_set_target_queue将多个串行的queue指定到了同一目标,那么着多个串行queue在目标queue上就是同步执行的,不再是并行执行。

    - (void)testTargetQueue {
        //1.创建目标队列
        dispatch_queue_t targetQueue = dispatch_queue_create("test.target.queue", DISPATCH_QUEUE_SERIAL);
        
        //2.创建3个串行队列
        dispatch_queue_t queue1 = dispatch_queue_create("test.1", DISPATCH_QUEUE_SERIAL);
        dispatch_queue_t queue2 = dispatch_queue_create("test.2", DISPATCH_QUEUE_SERIAL);
        dispatch_queue_t queue3 = dispatch_queue_create("test.3", DISPATCH_QUEUE_SERIAL);
        
        //3.将3个串行队列分别添加到目标队列
        dispatch_set_target_queue(queue1, targetQueue);
        dispatch_set_target_queue(queue2, targetQueue);
        dispatch_set_target_queue(queue3, targetQueue);
        
        
        dispatch_async(queue1, ^{
            NSLog(@"1 in");
            [NSThread sleepForTimeInterval:3.f];
            NSLog(@"1 out");
        });
        
        dispatch_async(queue2, ^{
            NSLog(@"2 in");
            [NSThread sleepForTimeInterval:2.f];
            NSLog(@"2 out");
        });
        dispatch_async(queue3, ^{
            NSLog(@"3 in");
            [NSThread sleepForTimeInterval:1.f];
            NSLog(@"3 out");
        });
    }
    

    输出:

    1 in
    1 out
    2 in
    2 out
    3 in
    3 out
    

    不懂就药问

    相关文章

      网友评论

        本文标题:多线程编程之GCD(二)

        本文链接:https://www.haomeiwen.com/subject/vmznwttx.html