0. Brief Introduction

GCD,全称Grand Central Dispath,是苹果开发的一种支持并行操作的机制。它的主要部件是一个FIFO队列和一个线程池,前者用来添加任务,后者用来执行任务。

GCD中的FIFO队列称为dispatch queue,它可以保证先进来的任务先得到执行(但不保证一定先执行结束)。

通过与线程池的配合,dispatch queue分为下面两种:

  • Serial Dispatch Queue -- 线程池只提供一个线程用来执行任务,所以后一个任务必须等到前一个任务执行结束才能开始。
  • Concurrent Dispatch Queue -- 线程池提供多个线程来执行任务,所以可以按序启动多个任务并发执行。

1. Basic Management

我们可以通过dispatch_queue_cretae来创建队列,然后用dispatch_release释放。比如下面两段代码分别创建串行队列和并行队列:

dispatch_queue_t serialQ = dispatch_queue_create("eg.gcd.SerialQueue", DISPATCH_QUEUE_SERIAL);
dispatch_async(serialQ, ^{
// Code here
});
dispatch_release(serialQ); dispatch_queue_t concurrentQ = dispatch_queue_create("eg.gcd.ConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQ, ^{
// Code here
});
dispatch_release(concurrentQ);

而系统默认就有一个串行队列main_queue和并行队列global_queue:

dispatch_queue_t globalQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, );
dispatch_queue_t mainQ = dispatch_get_main_queue();

通常,我们可以在global_queue中做一些long-running的任务,完成后在main_queue中更新UI,避免UI阻塞,无法响应用户操作:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ), ^{
// long-running task
dispatch_async(dispatch_get_main_queue(), ^{
// update UI
});
});

上面提到dispatch_async这个接口,用来提交blcok给指定queue进行异步执行。这个接口会在成功提交block后立即返回,然后继续执行下去。由于block是定义在栈上的,所以需要将其复制到堆上,见这里

与之相对应的是dispatch_sync接口,提交block以供同步执行。这个接口会等到block执行结束才返回,所以不需要复制block。So,如果在调用该接口在当前queue上指派任务,就会导致deadlock。维基百科上给了段示例代码:

dispatch_queue_t exampleQueue = dispatch_queue_create("com.example.unique.identifier", NULL );
dispatch_sync( exampleQueue,^{
dispatch_sync( exampleQueue,^{
printf("I am now deadlocked...\n");
});});
dispatch_release( exampleQueue );

如果追求的是并发,那么dispatch_sync有什么用呢?关于dispatch_sync的用途,SO上有讨论

2. Normal Control

  • dispatch_once

如果没有记错的话,在iOS Con 2012上,大众点评的同学分享了个Topic叫《iOS开发最佳实践》,开篇讲singleton实现的演进(怎么演进都有可以挑的刺),后面转折说要把精力放到用户看得到的地方。

如果把singleton和best practice放在一起,那么我很容易联想到dispatch_once这个函数,它可以保证整个应用程序生命周期中某段代码只被执行一次

static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// code to be executed once
});
  • dispatch_after

有时候我们需要等个几秒钟然后做个动画或者给个提示,这时候可以用dispatch_after这个函数:

double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
// code to be executed on the main queue after delay
});
  • dispatch_set_target_queue

通过dispatch_set_target_queue函数可以设置一个dispatch queue的优先级,或者指定一个dispatch source相应的事件处理提交到哪个queue上。

dispatch_set_target_queue(serialQ, globalQ);  
  • dispatch_apply

执行某个代码片段若干次。

dispatch_apply(, globalQ, ^(size_t index) {
// do sth. 10 times
});
  • dispatch group

Dispatch Group机制允许我们监听一组任务是否完成:

dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, concurrentQ, blk0);
dispatch_group_async(group, concurrentQ, blk1);
dispatch_group_async(group, concurrentQ, blk2);
dispatch_group_notify(group, mainQ, ^{
// update UI
});
dispatch_release(group);

或者说同步地等待一段时间看是否结束:

dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 1ull * NSEC_PER_SEC);
dispatch_group_wait(group, time);
  • dispatch_barrier_async

通过dispatch_barrier_async函数提交的任务会等它前面的任务执行结束才开始,然后它后面的任务必须等它执行完毕才能开始。

dispatch_async(concurrentQ, blk0);
dispatch_async(concurrentQ, blk1);
dispatch_barrier_async(concurrentQ, blk_barrier);
dispatch_async(concurrentQ, blk2);

这份官方文档很清晰地按功能为GCD相关函数进行了分类。

原文链接:http://blog.csdn.net/jasonblog/article/details/7816999

IOS开发GCD小结的更多相关文章

  1. ios开发--GCD使用介绍:4-延迟执行操作

    在开发过程中,我们有时会希望把一些操作封装起来延迟一段时间后再执行.iOS开发中,有两种常用的方法可以实现延迟执行,一种是使用GCD,另外一种是使用NSRunLoop类中提供的方法. 1.使用GCD实 ...

  2. AIR for IOS开发问题小结

    昨天终于成功地向APP STORE提交了应用,个人感觉用AIR做IOS开发就是个坑啊.出了问题之后,问苹果的技术支持,人家说“对于非XCODE环境下开发及发布所造成的问题我们在资料库中无法找到相应的解 ...

  3. iOS开发——GCD多线程详解

    GCD多线程详解 1. 什么是GCD Grand Central Dispatch 简称(GCD)是苹果公司开发的技术,简单来说,GCD就是iOS一套解决多线程的机制,使用GCD能够最大限度简化多线程 ...

  4. IOS开发 GCD介绍: 基本概念和Dispatch Queue

    iOS的三种多线程技术 1.NSThread 每个NSThread对象对应一个线程,量级较轻(真正的多线程) 2.以下两点是苹果专门开发的“并发”技术,使得程序员可以不再去关心线程的具体使用问题 ØN ...

  5. iOS开发-GCD和后台处理

    一些生命周期函数的调用时间 打开应用时,调用 applicationWillEnterForeground: applicationDidBecomeActive: 按Home键,调用 applica ...

  6. iOS开发——GCD总结

    Grand Central Dispatch,简称GCD,在异步执行任务的技术之一. 一般将应用程序中记述的线程管理用的代码在系统级中实现,开发者只需要定义想执行的任务并追加到适当的Dispatch ...

  7. iOS开发-Autolayout小结

    昨天重点学习了下Autolayout,把以前没有吃透的概念重新理解了下,现在感觉整个人都是棒棒哒. 上一个项目是使用计算坐标代码的方式来布局UI界面,这种方式的缺点在于当苹果发布新尺寸设备时需要重写代 ...

  8. iOS开发GCD的简单使用

    - (void)viewDidLoad { [super viewDidLoad]; // gcd 可以充分调用设备的 cpu 发挥最大性能,在 C 语言基础之上封装的 // dispatch_que ...

  9. iOS开发GCD(3)-数据安全

    /* 多个线程可能访问同一块资源,造成数据错乱和数据安全问题 为代码添加同步锁(互斥锁) */ -(void)synchronized{ @synchronized(self){ //需要锁住的代码, ...

随机推荐

  1. 终极之shell-zsh全解析

    什么是Zsh Zsh是一款强大的虚拟终端,既是一个系统的虚拟终端,也可以作为一个脚本语言的交互解析器. Zsh的一些特性 兼容bash,原来使用bash的兄弟切换过来毫无压力. 强大的历史纪录功能,在 ...

  2. tsar的使用

    项目地址https://github.com/alibaba/tsar 安装 $ git clone git://github.com/kongjian/tsar.git $ cd tsar $ ma ...

  3. 02_MySQL DQL_条件查询

    #查询2:条件查询 /*语法: select 查询列表 from 表名 where 筛选条件; 执行顺序:找到表,逐行筛选,选出行的相关列呈现 分类: 1)按条件表达式筛选 条件运算符:> &l ...

  4. 51nod 1187 寻找分数

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  5. jqueryUI之datepicker日历插件的介绍和使用

    jQuery UI很强大,其中的日期选择插件Datepicker是一个配置灵活的插件.我们可以自定义其展示方式,包括日期格式.语言.限制选择日期范围.添加相关按钮以及其它导航等.

  6. maven笔记(4)

    项目管理利器(Maven)——依赖范围(classPath:编译,运行,测试)1.compile:默认范围,编译测试运行都有效2.provided:在编译和测试时有效3.runtime:在测试和运行时 ...

  7. JavaScript encodeURIComponent()

    ■ 把字符串作为 URI 组件进行编码.JavaScript中有三个可以对字符串编码的函数,分别是: escape,encodeURI,encodeURIComponent,相应3个解码函数:unes ...

  8. JSP XML 数据处理

    JSP XML 数据处理 当通过HTTP发送XML数据时,就有必要使用JSP来处理传入和流出的XML文档了,比如RSS文档.作为一个XML文档,它仅仅只是一堆文本而已,使用JSP创建XML文档并不比创 ...

  9. HTML DOM(二):节点的增删改查

    上一篇讲述了DOM的基本知识,从其得知,在DOM眼中,HTML的每个成分都可以看作是节点(文档节点.元素节点.文本节点.属性节点.注释节点,其中,属性节点是属于元素节点),本篇的内容就是通过DOM对这 ...

  10. zookeeper常见错误

    1.在注册中心找不到对应的服务 这种错误是服务层代码没有成功注册到注册中心导致,请检查一下你的服务层代码是否添加了@service注解,并且该注解的包一定是com.alibaba.dubbo.conf ...