美文网首页
Object-C_GCD_摘抄

Object-C_GCD_摘抄

作者: 陈胜华 | 来源:发表于2016-08-05 17:15 被阅读377次

    说明:权当笔记,摘抄Romit_Lee,GCD全解析,非常感谢这位大神,担心取消文章了,请这位大神收下我膝盖吧!!!


    补充:什么是队列,什么是线程?
    许大大答:队列是数据结构,线程是CPU最小调度单元
    陈大大问:这两是怎么联系的?
    许大大答:

    如果做一个队列,把需要执行的线程放进去,队列就成了待执行的任务;
    如果做一个队列,把不用的线程放进去,队列就成了线程池

    1、dispatch_after-------------------------指定时间后追加
    2、dispatch_group_t-----------------------处理组
    3、dispatch_barrier_async-----------------queue中等待A执行后继续queue中追加到其他
    4、dispatch_sync--------------------------同步
    5、dispatch_apply-------------------------指定次数的重复追加
    6、dispatch_suspend&dispatch_resume-------暂停和继续
    7、dispatch_semaphore_t-------------------设置计数点
    8、dispatch_once_t------------------------只执行一次
    

    队列优先级

    优先级枚举 描述
    DISPATCH_QUEUE_PRIORITY_HIGH 优先级最高,在default,和low之前执行
    DISPATCH_QUEUE_PRIORITY_DEFAULT 默认优先级,在low之前,在high之后
    DISPATCH_QUEUE_PRIORITY_LOW 在high和default后执行
    DISPATCH_QUEUE_PRIORITY_BACKGROUND 提交到这个队列的任务会在high优先级的任务和已经提交到background队列的执行完后执行

    1.文字描述

    GCD英文全称:Grand Central Dispatch 翻译就是 宏大的中央调度,是苹果开发的一种支持并行操作的机制,基于C语言,提供了非常多强大的函数

    在了解GCD并使用之前,必须要掌握四个名词:串行,并发,同步,异步

    串行(Serial):
    一个任务执行完, 再执行下一个任务

    并发 (Concurrent):
    多个任务同时执行(自动开启多个线程),只有在异步函数下才有效

    同步(Synchronous):
    在当前线程中执行任务,不具备开启新线程的能力提交的任务在执行完成后才会返回同步函数: dispatch_sync()

    异步 (Asynchronous):
    在新的线程中执行任务, 具备开启线程的能力在新线程中执行任务,具备开启新线程的能力提交的任务立刻返回,在后台队列中执行异步函数: dispatch_async()


    2.Dispatch Queue

    Dispatch Queue是执行处理的等待队列, 按照先进先出(FIFO, First-In-First-Out)的顺序进行任务处理.
    开发者将需要执行的任务添加到合适的Dispatch Queue中即可,Dispatch Queue会根据任务添加的顺序先到先执行,其中有以下几种队列:另外, 队列分两种

    • 一种是串行队列(Serial Dispatch Queue)
    • 一种是并行队列(Concurrent Dispatch Queue).
    Dispatch Queue的种类 说明
    Serial Dispatch Queue(串行队列) 等待现在执行中处理结束
    Concurrent Dispatch Queue(并行队列) 不等待现在执行中处理结束
    //创建一个串行队列
    dispatch_queue_t serialQueue = dispatch_queue_create("com.serial.queue", DISPATCH_QUEUE_SERIAL);
    //创建一个并发队列
    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
    //第一个参数为队列名,第二个参数为队列类型,当然,第二个参数人如果写NULL,创建出来的也是一个串行队列。然后我们在异步线程来执行这个队列:
    

    另外系统为我们准备了两个队列

    main dispatch queue
    功能跟主线程一样,通过dispatch_get_main_queue()来获取,提交到main queue的任务实际上都是在主线程执行的,所以这是一个串行队列

    dispatch_queue_t queue = dispatch_get_main_queue();
    

    global dispatch queues
    系统给每个应用提供四个全局的并发队列,这四个队列分别有不同的优先级:高、默认、低以及后台,用户不能去创建全局队列,只能根据优先级去获取:

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);```
    
    -----
    
    #### 3.dispatch_sync&dispatch_async
    执行队列中任务的两种方式,**dispatch_sync**是同步任务,**dispatch_async**是异步任务
    
    1 .**用同步的方式执行任务(同步:synchronization)**, 只能在当前线程中执行任务,不具备开启新线程的能力
    
    

    /* *
    第一个参数:该任务所在的队列 *
    第二个参数:该任务要做的事情
    */
    dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);3

    
    * 假如我指定的队列A是串行队列,则该队列中只能有一个线程,也就是说我放在队列A中的任务,所以必须得一个一个的执行。不仅如此,在上面我们还手动选择了在队列A中用同步的方式执行任务,这也限制了,队列中的任务只能一个一个执行。
    * 假如我指定的队列A是并行队列,则该队列中可以开辟多个线程去执行任务,虽然如此,但由于我们在上面手动选择了在队列A中用同步的方式执行线程,所以队列A中的任务也只能一个一个去执行,**不能开辟多线程同时执行**。
    
    2.**用异步的方式执行任务(异步:asynchronous)**,可以在新的线程中执行任务,具备开启新线程的能力。
    
    

    dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

    
    * 假如此时我指定的队列B是并行队列,则表明该队列中可以存在多个线程,又因为我们采用的是异步的方式执行任务,所以在这个队列的任务可以实现同时运行。
    * 假如此时我指定的队列B是串行队列,则表明该队列中,只能有一个线程,所以尽管我采用异步的方式执行任务,但该队列中的任务还是只能一个一个的运行。
    
    *********************
    
    #### 4.创建的线程任务有四种执行方式
    ![](https://img.haomeiwen.com/i1387500/8b2b54271ac076cf.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    **1. 串行队列同步执行任务**
    * 同步不具有开辟新线程的能力,不会开辟新的线程去执行任务,会在当前程序的主线程中执行任务。
    * 按照串行的方式去执行任务
    
    

    -(void)syncSERIAL{
    NSLog(@"star");
    //不会开辟新的线程
    dispatch_queue_t queue=dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_SERIAL);
    dispatch_sync(queue, ^{
    NSLog(@"SERIAL_work_1 ");
    });
    dispatch_sync(queue, ^{
    NSLog(@"SERIAL_work_2 ");
    });
    dispatch_sync(queue, ^{
    NSLog(@"SERIAL_work_3 ");
    });
    NSLog(@"end");
    }

    //执行结果
    2016-07-20 20:08:09.695 GCD_Demo[8196:1029563] star
    2016-07-20 20:08:09.696 GCD_Demo[8196:1029563] SERIAL_work_1
    2016-07-20 20:08:09.696 GCD_Demo[8196:1029563] SERIAL_work_2
    2016-07-20 20:08:09.696 GCD_Demo[8196:1029563] SERIAL_work_3
    2016-07-20 20:08:09.696 GCD_Demo[8196:1029563] end

    **由于是同步操作,不能开辟线程,所以都是在主线程并按照顺序执**
    
    **2. 串行队列异步执行任务**
    * 异步具有创建新线程的能力,会开辟新的线程去执行任务
    * 按照串行的方式去执行任务
    
    

    -(void)asyncSERIAL{
    NSLog(@"star");
    //会开辟新的线程,但是是串行执行任务
    dispatch_queue_t queue=dispatch_queue_create("ki", DISPATCH_QUEUE_SERIAL);
    dispatch_async(queue, ^{
    [NSThread sleepForTimeInterval:3];
    NSLog(@"SERIAL_work_1 ");
    });
    dispatch_async(queue, ^{
    [NSThread sleepForTimeInterval:2];
    NSLog(@"SERIAL_work_2 ");
    });
    dispatch_async(queue, ^{
    NSLog(@"SERIAL_work_3 ");
    });
    NSLog(@"end");
    }

    //执行结果
    2016-07-20 20:09:58.494 GCD_Demo[8213:1031268] star
    2016-07-20 20:09:58.495 GCD_Demo[8213:1031268] end
    2016-07-20 20:10:01.496 GCD_Demo[8213:1031315] SERIAL_work_1
    2016-07-20 20:10:03.502 GCD_Demo[8213:1031315] SERIAL_work_2
    2016-07-20 20:10:03.502 GCD_Demo[8213:1031315] SERIAL_work_3

    
    **因为是异步操作,所以有个编号为2的子线程被开辟,但有因为是串行队列,所以只开辟了一个线程。最终造就了三个任务顺序执行。**
    
    **3. 并行队列同步执行任务**
    * 同步不具有创建新线程的能力,不会开辟新的线程去执行任务,会在当前程序的主线程去执行任务
    * 按照同步的方式去执行任务
    
    

    -(void)syncCONCURRENT{
    NSLog(@"star");
    //不会开辟新的线程
    //串行执行命令
    dispatch_queue_t queue=dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_CONCURRENT);
    dispatch_sync(queue, ^{
    [NSThread sleepForTimeInterval:3];
    NSLog(@"CONCURRENT_work_1 ");
    });
    dispatch_sync(queue, ^{
    [NSThread sleepForTimeInterval:2];
    NSLog(@"CONCURRENT_work_2 ");
    });
    dispatch_sync(queue, ^{
    NSLog(@"CONCURRENT_work_3 ");
    });
    NSLog(@"end");
    }

    //执行结果
    2016-07-20 20:13:03.753 GCD_Demo[8232:1033759] star
    2016-07-20 20:13:06.755 GCD_Demo[8232:1033759] CONCURRENT_work_1
    2016-07-20 20:13:08.756 GCD_Demo[8232:1033759] CONCURRENT_work_2
    2016-07-20 20:13:08.756 GCD_Demo[8232:1033759] CONCURRENT_work_3
    2016-07-20 20:13:08.757 GCD_Demo[8232:1033759] end

    
    **虽然并行队列决定了该队列中可以有多个线程,但由于是同步操作,不能开辟线程,所以还都是在主线程中按顺序执行。**
    
    ********
    
    **4. 并发队列异步执行任务(常用)**
    
    * 异步具有创建新线程的能力,会开辟新的线程去执行任务,不会在当前程序的主线程去执行任务
    * 按照并发的方式去执行任务
    
    

    -(void)asyncCONCURRENT{
    NSLog(@"star");
    //一个队列 为 每个任务开辟一个线程
    dispatch_queue_t queue=dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
    [NSThread sleepForTimeInterval:3];
    NSLog(@"CONCURRENT_work_1\n");
    });
    dispatch_async(queue, ^{
    [NSThread sleepForTimeInterval:2];
    NSLog(@"CONCURRENT_work_2 \n");
    });
    dispatch_async(queue, ^{
    NSLog(@"CONCURRENT_work_3 \n");
    });
    NSLog(@"end");
    }

    //执行结果
    2016-08-05 17:17:26.020 GCD方法测试[3310:248708] star
    2016-08-05 17:17:26.020 GCD方法测试[3310:248708] end
    2016-08-05 17:17:26.020 GCD方法测试[3310:248756] CONCURRENT_work_3
    2016-08-05 17:17:28.024 GCD方法测试[3310:248750] CONCURRENT_work_2
    2016-08-05 17:17:29.025 GCD方法测试[3310:248744] CONCURRENT_work_1

    
    ********
    #### 5.Dispatch Group
    当我们想在gcd queue中___所有的任务执行完毕___之后做些特定事情的时候,也就是队列的同步问题,如果队列是串行的话,那将该操作最后添加到队列中即可,但如果队列是并行队列的话,这时候就可以利用dispatch_group来实现了,dispatch_group能很方便的解决同步的问题。dispatch_group_create可以创建一个group对象,然后可以添加block到该组里面,下面看下它的一些用法:
    
    * **dispatch_group_notify**是通过异步的方式通知,所以,不会阻塞线程
    
    
    

    -(void)asyncGroupNotify {
    NSLog(@"star");
    dispatch_group_t group=dispatch_group_create();
    dispatch_queue_t queue=dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_async(group, queue, ^{
    [NSThread sleepForTimeInterval:1];
    NSLog(@"group_work_1");
    });
    dispatch_group_async(group, queue, ^{
    [NSThread sleepForTimeInterval:6];
    NSLog(@"group_work_2");
    });
    dispatch_group_async(group, queue, ^{
    [NSThread sleepForTimeInterval:2];
    NSLog(@"group_work_3");
    });

    dispatch_group_notify(group, queue, ^{
        NSLog(@"dispatch_group_Notify 结束");
    });
    

    }

    //执行结果
    2016-08-05 17:19:09.233 GCD方法测试[3345:250324] star
    2016-08-05 17:19:10.238 GCD方法测试[3345:250379] group_work_1
    2016-08-05 17:19:15.237 GCD方法测试[3345:250369] group_work_2
    2016-08-05 17:19:15.238 GCD方法测试[3345:250369] dispatch_group_Notify 结束

    
    * **dispatch_group_wait**
    会阻塞当前线程,知道任务都完成时才会继续执行下面的代码
    
    

    -(void)asyncGroupWait {

    NSLog(@"star");
    dispatch_group_t group=dispatch_group_create();
    dispatch_queue_t queue=dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_async(group, queue, ^{
        [NSThread sleepForTimeInterval:1];
        NSLog(@"group_work_1");
    });
    dispatch_group_async(group, queue, ^{
        [NSThread sleepForTimeInterval:6];
        NSLog(@"group_work_2");
    });
    dispatch_group_async(group, queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"group_work_3");
    });
    
    //在此设置了一个12秒的等待时间,如果group的执行结束没有到12秒那么就返回0
    //如果执行group的执行时间超过了12秒,那么返回非0 数值,
    //在使用dispatch_group_wait函数的时候,会阻塞当前线程,阻塞的时间 在wait函数时间值和当前group执行时间值取最小的。
    long kk=dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, 12 * NSEC_PER_SEC));
    if(kk==0)
    {
        NSLog(@"dispatch_group_wait 结果1");
    }
    else
    {
        NSLog(@"dispatch_group_wait 结果2");
    }
    

    }
    //执行结果:
    2016-08-05 17:22:10.262 GCD方法测试[3398:252460] star
    2016-08-05 17:22:11.265 GCD方法测试[3398:252499] group_work_1
    2016-08-05 17:22:12.263 GCD方法测试[3398:252514] group_work_3

    
    * **dispatch_group_enter**&**dispatch_group_leave**
    假如我们不想使用dispatch_group_async异步的将任务丢到group中去执行,这时候就需要用到dispatch_group_enter跟dispatch_group_leave方法,这两个方法要配对出现,以下这两种方法是等价的:
    
    

    -(void)asyncGroupEnter {

    // 群组-统一监控一组任务
    dispatch_group_t group = dispatch_group_create();
    
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    
    // 1> 入组 -> 之后的 block 会被 group 监听
    // dispatch_group_enter 一定和 dispatch_group_leave 要配对出现
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        NSLog(@"dispatch_async_work1");
        
        // block 的末尾,所有任务执行完毕后,添加一个出组
        dispatch_group_leave(group);
    });
    
    //  再次入组
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:6];
        
        NSLog(@"dispatch_async_work1");
        
        // block 的末尾,所有任务执行完毕后,添加一个出组
        dispatch_group_leave(group);
    });
    
    // 群组结束
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"OVER");
    });  
    NSLog(@"come here");
    

    }
    //执行结果:
    2016-08-05 17:24:17.857 GCD方法测试[3428:254365] dispatch_async_work1
    2016-08-05 17:24:17.857 GCD方法测试[3428:254326] come here
    2016-08-05 17:24:23.860 GCD方法测试[3428:254373] dispatch_async_work1
    2016-08-05 17:24:23.861 GCD方法测试[3428:254326] OVER

    
    ********
    
    #### 6. ***Dispatch Block***
    添加到gcd队列中执行的任务是以block的形式添加的,block封装了需要执行功能,block带来的开发效率提升就不说了,gcd跟block可以说是一对好基友,能够很好的配合使用。
    
    

    -(void)dispatchBlock {

    dispatch_queue_t queue = dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_SERIAL);
    dispatch_block_t block=dispatch_block_create(0, ^{
        NSLog(@"dispatchBlock_work");
    });
    
    dispatch_sync(queue, block);
    

    }

    
    * **1.dispatch_block_wait**
    当需要等待前面的任务执行完毕时,我们可以使用dispatch_block_wait这个接口,设置等待时间DISPATCH_TIME_FOREVER会一直等待直到前面的任务完成.用法跟dispatch_group_wait类似
    
    

    -(void)dispatchBlockWait {

    dispatch_queue_t queue = dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_SERIAL);
    dispatch_block_t block = dispatch_block_create(0, ^{
        NSLog(@"before sleep");
        [NSThread sleepForTimeInterval:6];
        NSLog(@"after sleep");
    });
    dispatch_async(queue, block);
    //等待前面的任务执行完毕
    long kk=dispatch_block_wait(block, dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC));
    if(kk==0)
    {
        NSLog(@"coutinue");
    }
    else
    {
        NSLog(@"timeOut!!!");
    }
    

    }
    //执行结果:
    2016-08-05 17:28:14.035 GCD方法测试[3472:257054] before sleep
    2016-08-05 17:28:17.036 GCD方法测试[3472:257007] timeOut!!!
    2016-08-05 17:28:20.036 GCD方法测试[3472:257054] after sleep

    
    * **2.dispatch_block_notify**dispatch_block_notify
    当观察的某个block执行结束之后立刻通知提交另一特定的block到指定的queue中执行,该函数有三个参数,第一参数是需要观察的block,第二个参数是被通知block提交执行的queue,第三参数是当需要被通知执行的block
    
    

    -(void)dispatchBlockNotify {

    dispatch_queue_t queue = dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_SERIAL);
    dispatch_block_t previousBlock = dispatch_block_create(0, ^{
        NSLog(@"previousBlock begin");
        [NSThread sleepForTimeInterval:2];
        NSLog(@"previousBlock done");
    });
    dispatch_async(queue, previousBlock);
    dispatch_block_t notifyBlock = dispatch_block_create(0, ^{
        NSLog(@"notifyBlock");
    });
    //当previousBlock执行完毕后,提交notifyBlock到global queue中执行
    dispatch_block_notify(previousBlock, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), notifyBlock);
    

    }

    //执行结果:
    2016-08-05 17:30:48.658 GCD方法测试[3519:259085] previousBlock begin
    2016-08-05 17:30:50.663 GCD方法测试[3519:259085] previousBlock done
    2016-08-05 17:30:50.664 GCD方法测试[3519:259099] notifyBlock

    
    * ***3. dispatch_block_cancel***
    
    可以取消提交到队列的block
    
    

    -(void)dispatchBlockCancel {

    dispatch_queue_t queue = dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_CONCURRENT);
    dispatch_block_t block1 = dispatch_block_create(0, ^{
        NSLog(@"block1 begin");
        [NSThread sleepForTimeInterval:1];
        NSLog(@"block1 done");
    });
    dispatch_block_t block2 = dispatch_block_create(0, ^{
        NSLog(@"block2 ");
    });
    dispatch_async(queue, block1);
    dispatch_async(queue, block2);
    dispatch_block_cancel(block2);
    

    }

    //执行结果:
    2016-08-05 17:32:33.129 GCD方法测试[3541:261055] block1 begin
    2016-08-05 17:32:34.131 GCD方法测试[3541:261055] block1 done

    
    ********
    
    #### 7.dispatch_after
    来延迟执行的GCD方法,因为在主线程中我们不能用sleep来延迟方法的调用,所以用它是最合适的,我们做一个简单的例子:
    
    

    -(void)dispatchAfter {

    NSLog(@"dispatchAfter_star");
    int64_t time=2*NSEC_PER_SEC;
    
    dispatch_queue_t mainQueue=dispatch_get_main_queue();
    
    for (int i=0; i<5; i++) {
        dispatch_time_t disTime=dispatch_time(DISPATCH_TIME_NOW, time*i);
        
        dispatch_after(disTime, mainQueue, ^{
            NSLog(@"dispatchAfter_work");
        });
    }
    

    }
    //执行结果:
    2016-08-05 17:38:24.721 GCD方法测试[3592:265091] dispatchAfter_star
    2016-08-05 17:38:26.722 GCD方法测试[3592:265091] dispatchAfter_work
    2016-08-05 17:38:28.722 GCD方法测试[3592:265091] dispatchAfter_work
    2016-08-05 17:38:31.319 GCD方法测试[3592:265091] dispatchAfter_work
    2016-08-05 17:38:33.521 GCD方法测试[3592:265091] dispatchAfter_work

    
    ********
    
    #### 8.dispatch_apply
    dispatch_apply类似一个for循环,会在指定的dispatch queue中运行block任务n次,如果队列是并发队列,则会并发执行block任务,dispatch_apply是一个同步调用,block任务执行n次后才返回。
    
    
    

    -(void)dispatchApply {

    dispatch_queue_t queue = dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_apply(6, queue, ^(size_t i) {
        NSLog(@"do a job %zu times",i);
        
    });
    NSLog(@"go on");
    

    }
    //执行结果:
    2016-08-05 17:35:22.954 GCD方法测试[3566:263074] do a job 3 times
    2016-08-05 17:35:22.954 GCD方法测试[3566:263309] do a job 4 times
    2016-08-05 17:35:22.954 GCD方法测试[3566:263302] do a job 2 times
    2016-08-05 17:35:22.954 GCD方法测试[3566:263289] do a job 1 times
    2016-08-05 17:35:22.954 GCD方法测试[3566:263297] do a job 0 times
    2016-08-05 17:35:22.954 GCD方法测试[3566:263310] do a job 5 times
    2016-08-05 17:35:22.955 GCD方法测试[3566:263074] go on

    
    ********
    
    #### 9.dispatch_once
    整个程序运行中只会执行一次,使用dispatch_once可以简化代码并且彻底保证线程安全,开发者根本无须担心加锁或者同步。所有问题都由GCD在底层处理。由于每次调用时都必须使用完全相同的标记,所以标记要声明成static。所以用在单例模式上是最好的
    
    

    static SingletonTimer * instance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
    instance = [[SingletonTimer alloc] init];
    });

    return instance;

    
    ********
    
    #### 10. dispatch_barrier_async
    dispatch_barrier_async用于等待前面的任务执行完毕后自己才执行,而它后面的任务需等待它完成之后才执行。一个典型的例子就是数据的读写,通常为了防止文件读写导致冲突,我们会创建一个串行的队列,所有的文件操作都是通过这个队列来执行,比如FMDB,这样就可以避免读写冲突。不过其实这样效率是有提升的空间的,当没有更新数据时,读操作其实是可以并行进行的,而写操作需要串行的执行
    
    
    

    -(void)diapatchBarrier {

    dispatch_queue_t queue = dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:6];
        NSLog(@"dispatch_async_work1");
    });
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"dispatch_async_work2");
    });
    dispatch_barrier_async(queue, ^{
        NSLog(@"dispatch_async_work3");
        [NSThread sleepForTimeInterval:1];
        
    });
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:1];
        NSLog(@"dispatch_async_work4");
    });
    

    }
    //执行结果:
    2016-08-05 17:40:43.602 GCD方法测试[3624:266832] dispatch_async_work2
    2016-08-05 17:40:47.603 GCD方法测试[3624:266840] dispatch_async_work1
    2016-08-05 17:40:47.603 GCD方法测试[3624:266840] dispatch_async_work3
    2016-08-05 17:40:49.611 GCD方法测试[3624:266840] dispatch_async_work4

    
    ********
    
    #### 11.dispatch_set_target_queue
    * 系统的Global Queue是可以指定优先级的,那我们可以用到dispatch_set_target_queue这个方法来指定自己创建队列的优先级
    
    

    -(void)DispatchSet {

    dispatch_queue_t serialDiapatchQueue=dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_SERIAL);
    dispatch_queue_t dispatchgetglobalqueue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
    dispatch_set_target_queue(serialDiapatchQueue, dispatchgetglobalqueue);
    dispatch_async(serialDiapatchQueue, ^{
        NSLog(@"我优先级低,先让让");
    });
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"我优先级高,我先block");
    });
    

    }
    //执行结果
    2016-08-05 17:41:52.856 GCD方法测试[3641:267973] 我优先级高,我先block
    2016-08-05 17:41:52.856 GCD方法测试[3641:267982] 我优先级低,先让让

    
    * 2.dispatch_set_target_queue除了能用来设置队列的优先级之外,还能够创建队列的层次体系,当我们想让不同队列中的任务同步的执行时,我们可以创建一个串行队列,然后将这些队列的target指向新创建的队列即可
    
    
    

    -(void)dispatchSet2 {

    dispatch_queue_t targetQueue = dispatch_queue_create("target_queue", DISPATCH_QUEUE_SERIAL);
    dispatch_queue_t queue1 = dispatch_queue_create("queue1", DISPATCH_QUEUE_SERIAL);
    dispatch_queue_t queue2 = dispatch_queue_create("queue2", DISPATCH_QUEUE_CONCURRENT);
    
    
    dispatch_set_target_queue(queue1, targetQueue);
    dispatch_set_target_queue(queue2, targetQueue);
    
    dispatch_async(queue1, ^{
        [NSThread sleepForTimeInterval:3.f];
        NSLog(@"do job1");
        
    });
    dispatch_async(queue2, ^{
        [NSThread sleepForTimeInterval:2.f];
        NSLog(@"do job2");
        
    });
    dispatch_async(queue2, ^{
        [NSThread sleepForTimeInterval:1.f];
        NSLog(@"do job3");
        
    });
    

    }
    //执行结果
    2016-08-05 17:44:50.988 GCD方法测试[3713:271558] do job1
    2016-08-05 17:44:52.994 GCD方法测试[3713:271558] do job2
    2016-08-05 17:44:53.999 GCD方法测试[3713:271558] do job3

    相关文章

      网友评论

          本文标题:Object-C_GCD_摘抄

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