dispatch_async 和dispatch_sync GCD

GCD编程的核心就是dispatch队列,dispatch block的执行最终都会放进某个队列中去进行


1. dispatch_queue_t queue = dispatch_queue_create("com.dispatch.serial", DISPATCH_QUEUE_SERIAL); //生成一个串行队列,队列中的block按照先进先出(FIFO)的顺序去执行,实际上为单线程执行。第一个参数是队列的名称,在调试程序时会非常有用,所有尽量不要重名了。


2. dispatch_queue_t queue = dispatch_queue_create("com.dispatch.concurrent", DISPATCH_QUEUE_CONCURRENT); //生成一个并发执行队列,block被分发到多个线程去执行


3. dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //获得程序进程缺省产生的并发队列,可设定优先级来选择高、中、低三个优先级队列。由于是系统默认生成的,所以无法调用dispatch_resume()dispatch_suspend()来控制执行继续或中断。需要注意的是,三个队列不代表三个线程,可能会有更多的线程。并发队列可以根据实际情况来自动产生合理的线程数,也可理解为dispatch队列实现了一个线程池的管理,对于程序逻辑是透明的。


官网文档解释说共有三个并发队列,但实际还有一个更低优先级的队列,设置优先级为DISPATCH_QUEUE_PRIORITY_BACKGROUNDXcode调试时可以观察到正在使用的各个dispatch队列。


4. dispatch_queue_t queue = dispatch_get_main_queue(); //获得主线程的dispatch队列,实际是一个串行队列。同样无法控制主线程dispatch队列的执行继续或中断。

接下来我们可以使用dispatch_asyncdispatch_sync函数来加载需要运行的block

dispatch_async(queue, ^{

      //block具体代码

}); //异步执行block,函数立即返回


dispatch_sync(queue, ^{

      //block具体代码

}); //同步执行block,函数不返回,一直等到block执行完毕。编译器会根据实际情况优化代码,所以有时候你会发现block其实还在当前线程上执行,并没用产生新线程。


那实际运用中,一般可以用dispatch这样来写,常见的网络请求数据多线程执行模型:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

      //子线程中开始网络请求数据

      //更新数据模型

      dispatch_sync(dispatch_get_main_queue(), ^{

            //在主线程中更新UI代码

          });

});


    dispatch队列是线程安全的,可以利用串行队列实现锁的功能。比如多线程写同一数据库,需要保持写入的顺序和每次写入的完整性,简单地利用串行队列即可实现:

    dispatch_queue_t queue1 = dispatch_queue_create("com.dispatch.writedb", DISPATCH_QUEUE_SERIAL);

    - (void)writeDB:(NSData *)data

    {

          dispatch_async(queue1, ^{            

                //write database

              });

    } 

    下一次调用writeDB:必须等到上次调用完成后才能进行,保证writeDB:方法是线程安全的。

    

    dispatch队列还实现其它一些常用函数,包括:

    void dispatch_apply(size_t iterations, dispatch_queue_t queue, void (^block)(size_t)); //重复执行block,需要注意的是这个方法是同步返回,也就是说等到所有block执行完毕才返回,如需异步返回则嵌套在dispatch_async中来使用。多个block的运行是否并发或串行执行也依赖queue的是否并发或串行。

    void dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block); //这个函数可以设置同步执行的block,它会等到在它加入队列之前的block执行完毕后,才开始执行。在它之后加入队列的block,则等到这个block执行完毕后才开始执行。

    void dispatch_barrier_sync(dispatch_queue_t queue, dispatch_block_t block); //同上,除了它是同步返回函数

    void dispatch_after(dispatch_time_t when, dispatch_queue_t queue, dispatch_block_t block); //延迟执行block

    最后再来看看dispatch队列的一个很有特色的函数:

    void dispatch_set_target_queue(dispatch_object_t object, dispatch_queue_t queue);

    它会把需要执行的任务对象指定到不同的队列中去处理,这个任务对象可以是dispatch队列,也可以是dispatch源(以后博文会介绍)。而且这个过程可以是动态的,可以实现队列的动态调度管理等等。比如说有两个队列dispatchAdispatchB,这时把dispatchA指派到dispatchB

    dispatch_set_target_queue(dispatchA, dispatchB);

    那么dispatchA上还未运行的block会在dispatchB上运行。这时如果暂停dispatchA运行:

    dispatch_suspend(dispatchA);

    则只会暂停dispatchA上原来的block的执行,dispatchBblock则不受影响。而如果暂停dispatchB的运行,则会暂停dispatchA的运行。

   



dispatch_sync(),同步添加操作。他是等待添加进队列里面的操作完成之后在继续执行。

dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);

        NSLog(@"1");

        dispatch_sync(concurrentQueue, ^(){

            NSLog(@"2");

            [NSThread sleepForTimeInterval:10];

            NSLog(@"3");

        });

        NSLog(@"4");

        11:36:25.313 GCDSeTest[544:303] 1

        11:36:25.313 GCDSeTest[544:303] 2

        11:36:30.313 GCDSeTest[544:303] 3//模拟长时间操作

        11:36:30.314 GCDSeTest[544:303] 4

 


dispatch_async ,异步添加进任务队列,它不会做任何等待

 dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);

        NSLog(@"1");

        dispatch_async(concurrentQueue, ^(){

            NSLog(@"2");

            [NSThread sleepForTimeInterval:5];

            NSLog(@"3");

        });

        NSLog(@"4");

        11:42:43.820 GCDSeTest[568:303] 1

        11:42:43.820 GCDSeTest[568:303] 4

        11:42:43.820 GCDSeTest[568:1003] 2

        11:42:48.821 GCDSeTest[568:1003] 3//模拟长时间操作时间





   dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);

        dispatch_async(concurrentQueue, ^(){

            NSLog(@"dispatch-1");

        });

        dispatch_async(concurrentQueue, ^(){

            NSLog(@"dispatch-2");

        });

        dispatch_barrier_async(concurrentQueue, ^(){

            NSLog(@"dispatch-barrier");

         });

        dispatch_async(concurrentQueue, ^(){

            NSLog(@"dispatch-3");

        });

        dispatch_async(concurrentQueue, ^(){

            NSLog(@"dispatch-4");  

        });

首先执行这段代码,并行队列里面异步4个任务。那么4个任务完成的先后是无法保证的。

如果加入被注释掉的那段代码,加入了barrier,那么在并行队列中的1234 4个任务的完成次序如何?

我跑了几次代码,最终结果都有两个相同点,1:34任务必定在12任务同时完成之后才被执行。2:12,34之间的执行次序不定

代码的第一行  DISPATCH_QUEUE_CONCURRENT 代表这个queue 是并发性质的。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值