读书笔记【1】 Grand Central Dispatch


简答的复习了一下GCD的一些简单操作,这里做一个笔记,方便以后查看。

  • Dispatch Queue
    • 自定义串、并行队列
    • 程序进程缺省队列
    • 主线程队列
  • 同步/异步、串行/并行使用
  • 死锁问题
  • dispatch_after
  • dispatch_group

Dispatch Queue

  • Serial Dispatch Queue 按添加进队列的顺序(先进先出)一个接一个的执行

  • Concurrent Dispatch Queue 并发执行队列里的任务

1.1 自定义串、并行队列

并行队列:DISPATCH_QUEUE_CONCURRENT
串行队列:DISPATCH_QUEUE_SERIAL
复制代码
//创建一个名称为‘com.company.xxx’的串行队列
dispatch_queue_t serialQueue = dispatch_queue_create("com.company.xxx", DISPATCH_QUEUE_SERIAL);

//创建一个名称为‘com.xxx’的并行队列
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.company.xxx", DISPATCH_QUEUE_CONCURRENT);
复制代码

Note: 1)参数一是队列的名称,一般是使用倒序的全域名。虽然可以不给队列指定一个名称,但是有名称的队列可以让我们在遇到问题时更好调试 2)当参数二为nil时返回Serial Dispatch Queue(串行队列),如上面那个例子,当指定为DISPATCH_QUEUE_CONCURRENT时返回Concurrent Dispatch Queue(并行队列)

1.2 程序进程缺省队列

高优先级队列:DISPATCH_QUEUE_PRIORITY_HIGH
中优先级队列:DISPATCH_QUEUE_PRIORITY_DEFAULT
低优先级队列:DISPATCH_QUEUE_PRIORITY_LOW
复制代码
//获取程序缺省并行队列,第二个参数固定为0
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
复制代码

Note: 1)需要注意的是,三个队列不代表三个线程,可能会有更多的线程。并发队列可以根据实际情况来自动产生合理的线程数,也可理解为dispatch队列实现了一个线程池的管理,对于程序逻辑是透明的。 2)获取Global Dispatch Queue的时候可以指定优先级,可以根据自己的实际情况来决定使用哪种优先级

1.3 主线程队列

//获取主线程串行队列
dispatch_queue_t queue = dispatch_get_main_queue();
复制代码

三者对比

队列串行并行
自定义队列
程序缺省队列×
主线程队列×

Note: 一般只在需要更新UI时我们才获取Main Dispatch Queue,其他情况下用Global Dispatch Queue就满足需求了

同步/异步、串行/并行使用

//异步执行block,函数立即返回
dispatch_async(queue, ^{

  //block具体代码

}); 

//同步执行block,函数不返回
dispatch_sync(queue, ^{

  //block具体代码

}); 
复制代码

举例:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //子线程中开始网络请求数据
        ···
        //更新数据模型
        dispatch_sync(dispatch_get_main_queue(), ^{
            //在主线程中更新UI代码
            self.view.backgroundColor = [UIColor orangeColor];
        });
    });
复制代码

Note: 尽可能避免使用dispatch_sync,嵌套使用时还容易引起程序死锁

死锁问题

  • 同步串行会出现死锁,同步并行不会造成死锁
  • 异步不管是串行还是并行都不会出现死锁
  • 异步嵌套同步或者同步嵌套异步就需要注意代码执行顺序

Note: 死锁原因:提交到主线程队列的时候,慎用同步dispatch_sync方法,有可能造成死锁。因为主线程队列是串行队列,要等队列里的任务一个一个执行。所以提交一个任务到队列,如果用同步方法就会阻塞住主线程,而主线程又要等主线程队列里的任务都执行完才能执行那个刚提交的,所以主线程队列里还有其他的任务的话,但他已经被阻塞住了,没法先完成队列里的其他任务,即,最后一个任务也没机会执行到,于是造成死锁。

dispatch_after

dispatch_after能让我们添加进队列的任务延时执行,比如想让一个Block在5秒后执行:

double delayTime = 5.0;

dispCatch_time_t dTime = dispatch_time(DISPATCH_TIME_NOW, 
(int64_t)(delayTime*NSEC_PER_SEC));

dispatch_after(dTime, dispatch_get_main_queue(), ^{
        //delayTime秒后执行block块
        NSLog(@"block执行");
    });
复制代码

dispatch_after的真正含义是在5秒后把任务添加进队列中,并不是表示在5秒后执行,大部分情况该函数能达到我们的预期,只有在对时间要求非常精准的情况下才可能会出现问题


【拓展】 延迟执行还有另外一种方式,那就是NSObject中的performSelector:withObject:afterDelay:以及performSelector:withObject:afterDelay:inModes:


dispatch_group

我们现在有3个Block要执行,我们不在乎它们执行的顺序,我们只希望在这3个Block执行完之后再执行某个操作。这个时候就需要使用dispatch_group

dispatch_group_t groupQueue = dispatch_group_create();

dispatch_group_async(groupQueue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSLog(@"1");
});

dispatch_group_async(groupQueue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSLog(@"2");
});

dispatch_group_async(groupQueue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSLog(@"3");
});

dispatch_group_notify(groupQueue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSLog(@"completion");
});
复制代码

在控制台打印的结果是: 2015-07-21 22:17:57.159 GCD[9606:1327380] 3 2015-07-21 22:17:57.159 GCD[9606:1327377] 2 2015-07-21 22:17:57.159 GCD[9606:1327379] 1 2015-07-21 22:17:57.159 GCD[9606:1327377] completion

Note: 输出的顺序与添加进队列的顺序无关,因为队列是Concurrent Dispatch Queue,但“completion”的输出一定是在最后的


再一次感谢您花费时间阅读这篇文章!

微博: @Danny_吕昌辉
博客: SuperDanny

2015 年 07月 15日

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值