Grand Central Dispatch (GCD)是Apple开发的一个多核编程的较新的解决方法。它主要用于优化应用程序以支持多核处理器以及其他对称多处理系统。它是一个在线程池模式的基础上执行的并行任务。在Mac OS X 10.6雪豹中首次推出,也可在IOS 4及以上版本使用。

设计

GCD是一个替代诸如NSThread等技术的很高效和强大的技术。GCD完全可以处理诸如数据锁定和资源泄漏等复杂的异步编程问题。GCD的工作原理是让一个程序,根据可用的处理资源,安排他们在任何可用的处理器核心上平行排队执行特定的任务。这个任务可以是一个功能或者一个程序段。
GCD仍然在一个很低的水平使用线程,但是它不需要程序员关注太多的细节。GCD创建的队列是轻量级的,苹果声明一个GCD的工作单元需要由15个指令组成。也就是说创造一个传统的线程很容易的就会需要几百条指令。
GCD中的一个任务可被用于创造一个被放置于队列的工作项目或者事件源。若果一个任务被分配到一个事件源,那么一个由功能或者程序块组成的工作单元会被放置于一个适当的队列中。苹果公司认为GCD相比于普通的一个接一个的执行任务的方式更为有效率。

功能

这个调度框架声明了几种数据类型和函数来创建和操作他们:
一、调度队列
所有的调度队列都是先进先出队列,因此,队列中的任务的开始的顺序和添加到队列中的顺序相同。GCD自动的为我们提供了一些调度队列,我们也可以创建新的用于具体的目的。
下面列出几种可用的调度队列类型以及如何使用。
二、调度资源
它是一个监视某些类型事件的对象。当这些事件发生时,它自动将一个block放入一个调度队列的执行例程中。
三、调度组
允许将多任务分组来方便后来加入执行。任务能作为一个组中的一个成员被加到队列中,客户端能用这个组对象来等待直到这个组中的所有任务完成。
四、调度信号量
允许客户端并行发布一定数量的任务。

相关代码

在开始之前,需要理解是要提供给GCD队列的是代码块,用于在系统或者用户创建的的队列上调度运行。
1.声明一个队列
如下会返回一个用户创建的队列:
dispatch_queue_t myQueue = dispatch_queue_create("com.iphonedevblog.post", NULL);其中,第一个参数是标识队列的,第二个参数是用来定义队列的参数(目前不支持,因此传入NULL)。
2.执行一个队列
如下会异步执行传入的代码:
dispatch_async(myQueue, ^{ [self doSomething]; });其中,首先传入之前创建的队列,然后提供由队列运行的代码块。
3.声明并执行一个队列
如果不需要保留要运行的队列的引用,可以通过如下代码实现之前的功能:
dispatch_async(dispatch_queue_create ("com.iphonedevblog.post", NULL), ^{ [self doSomething]; });暂停一个队列
如果需要暂停一个队列,可以调用如下代码。暂停一个队列会阻止和该队列相关的所有代码运行。
dispatch_suspend(myQueue);恢复一个队列
如果暂停一个队列不要忘记恢复。暂停和恢复的操作和内存管理中的retain和release类似。调用dispatch_suspend会增加暂停计数,而dispatch_resume则会减少。队列只有在暂停计数变成零的情况下才开始运行。dispatch_resume(myQueue);
4.从队列中在主线程运行代码
有些操作无法在异步队列运行,因此必须在主线程(每个应用都有一个)上运行。UI绘图以及任何对NSNotificationCenter的调用必须在主线程长进行。在另一个队列中访问主线程并运行代码的示例如下:
dispatch_sync(dispatch_get_main_queue(), ^{ [self dismissLoginWindow]; });注意,dispatch_suspend (以及dispatch_resume)在主线程上不起作用。

实例

可以在John Siracusa的ArsTechnica博客文章Snow Leopard review中找到两个演示如何使用Grand Central Dispatch的例子。首先,一个处理文档的应用程序有一个名为analyzeDocument函数,会做一些统计文档的单词和段落的事情。通常情况下,这将是一个快速的过程,并在用户根本没注意到按下一个键和结果显示出来之间的延迟就已经在主线程中执行好了。
-(IBAction)analyzeDocument:(NSButton*)sender{
NSDictionary*stats=[myDoc analyze];
[myModel setDict:stats];
[myStatsViewsetNeedsDisplay:YES];
[stats release];
}
如果一个文档太大并且需要很长的时间去执行,那么主线程将会暂停等待这个函数完成。如果花了很长的时间,那么用户就会注意到这个延迟,应用程序甚至会没有响应。这个问题的解决方案如下:
-(IBAction)analyzeDocument:(NSButton*)sender{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{
NSDictionary*stats=[myDoc analyze];
dispatch_async(dispatch_get_main_queue(),^{
[myModel setDict:stats];
[myStatsView setNeedsDisplay:YES];
[stats release];});
});
}
在这里,[myDoc analyze]的调用先被放置在了一个块中,然后进入一个全局并发队列里。在完成[myDoc analyze]的运行之后,一个新的块放置在主队列里(应用程序主线程在上面运行),更新了GUI(这是必要的,因为GUI只能由主线程更新)。通过这两个小的改动,开发人员就避免了能被用户看到的潜在的暂停并且使得应用程序更好的利用硬件资源。
第二个例子是一个并行的for循环:
for(i=0;i<count;i++){
results[i]=do_work(data,i);
}
total=summarize(results,count);
这段代码调用的do_work函数统计次数,将第i次的结果赋值给数组的第i个元素,然后在循环结束之后调用summarize函数。这些操作时顺序执行的,实际上并不需要这样。假设do_work函数不需要其他函数调用的结果,那么这些调用就可以同时运行了。这就是在GCD中的做法:
dispatch_apply(count,dispatch_get_global_queue(0,0),^(size_ti){
results[i]=do_work(data,i);
});
total=summarize(results,count);
这里,dispatch_apply运行传递来的块,在全局队列中放入每一次调用,并且给每次块调用一个从0到n-1的不同的数字。这样就允许操作系统通过当前的硬件和系统负载选择最佳的线程数来分配合适的工作。dispatch_apply知道所有的在给定队列的块运行完成才返回,这样就可以保证在调用summarize之前完成原来的循环里的所有事情。
程序员可以创建自己的任务队列,他们必须串行执行,但可在一个单独的线程中执行。一个新的队列可以像这样被创建:
dispatch_queue_t exampleQueue;
exampleQueue=dispatch_queue_create("com.example.unique.identifier",NULL);
//exampleQueue may be used here.
dispatch_release(exampleQueue);
必须小心,避免在队列中分配的块同步的放在同一队列的另一个块中,这是保证不会发生死锁情况。这样的代码可能会做下面的事情:
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);

GCD 多线程的更多相关文章

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

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

  2. GCD多线程的一个全面的题目

    GCD多线程的一个全面的题目  

  3. [Xcode 实际操作]八、网络与多线程-(22)使用GCD多线程技术异步下载图片

    目录:[Swift]Xcode实际操作 本文将演示如何使用使用GCD多线程技术异步下载图片. Grand Central Dispatch(GCD) 是 Apple 开发的一个多核编程的较新的解决方法 ...

  4. Object-C关于GCD多线程的使用

    ```objc1 使用Crearte函数创建的并发队列和全局并发队列的主要区别: 1)全局并发队列在整个应用程序中本身是默认存在的并且对应有高优先级.默认优先级.低优先级和后台优先级一共四个并发队列, ...

  5. iOS开发——多线程篇——NSOperation(基于GCD多线程编程),下载图片并合成新图片

    一.NSOperation的基本概念1.简介NSOperation的作用配合使用NSOperation和NSOperationQueue也能实现多线程编程 NSOperation和NSOperatio ...

  6. GCD 多线程 初探

    GCD编程的核心就是dispatch队列,dispatch block的执行最终都会放进某个队列中去进行,它类似NSOperationQueue但更复杂也更强大,并且可以嵌套使用.所以说,结合bloc ...

  7. ios 使用GCD 多线程 教程

    什么是GCD Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法.该方法在Mac OS X 10.6雪豹中首次推出,并随后被引入到了iOS4.0中.GCD ...

  8. ios开发:GCD多线程

    ios有三种多线程编程技术,分别是NSThread,Cocoa NSOperation和GCD,GCD全称Grand Central Dispatch 是Apple开发的一个多核编程的解决方法,在iO ...

  9. GCD多线程

    GCD本质线程自动管理指令包 GCD优点: 1.GCD 本身自带有线程锁的效果,能通过推迟昂贵计算任务并在后台运行它们来改善应用的响应性能. 2.GCD 提供了更易于使用的并发模型(效果方面类似于对锁 ...

  10. iOS——GCD多线程

    1> 概述 Grand Central Dispatch (GCD)是Apple开发的一种多核编程技术.主要用于优化应用程序以支持多核处理器以及其他对称多处理系统. GCD提供函数实现多线程开发 ...

随机推荐

  1. Google maps library的使用

    公司的项目中用到了google地图API, 使用Google API开发就会用到Marker, 用来在google 地图上标注位置 但是google marker使用过程中也有个问题,就是如果在goo ...

  2. Linux就是这个范儿之第一次亲密接触(3)

    原创作品,允许转载,转载时请务必以超链接形式标明文章原始出处 .作者信息和本声明.否则将追究法律责 1.4 返璞归真的命令行 有一种说法,现代计算机不是靠电力驱动,而是靠“鼠标”.多少应用程序的界面需 ...

  3. MySQL订单分库分表多维度查询

    转自:http://blog.itpub.net/29254281/viewspace-2086198/ MySQL订单分库分表多维度查询  MySQL分库分表,一般只能按照一个维度进行查询. 以订单 ...

  4. 9 个让 JavaScript 调试更简单的 Console 命令

    一.显示信息的命令 <!DOCTYPE html> <html> <head> <title>常用console命令</title> < ...

  5. NSDateFormatter 问题

    NSDateFormatter *inputDateFormatter = [[NSDateFormatter alloc] init]; NSString *inputDateStr = @&quo ...

  6. 【50】了解new和delete的合理替换时机

    1.有时候,我们替换掉编译器提供的new或者delete.首先思考,为什么想要替换?下面是三个常见理由: a.用来检测运用上的错误,超额分配一些内存,再额外的空间放置一些内存: b.为了强化效能,编译 ...

  7. 【转】通过CMD命令设置定时关机及ShutDown命令大全

    经常会遇到这种情况:现在有个事情要离开很长时间,到那还在下载一个东西仅差10分钟就完成了,或者杀毒之类,不想让电脑一直开着也不想现在就停止工作.这是就会用到定时关机. 电脑系统设置(CMD命令)智能关 ...

  8. PCL 点云数据操作 OpenCV遍历数据

    1.对于点云类型实例cloud,对其第i个点进行赋值操作,使用cloud.point[i].x 和 cloud.point[i].y 和cloud.point[i].z 分别对其XYZ坐标赋值. cl ...

  9. 记 Ubuntu14.04 Monodevelop 安装的两个问题

    1. Monodevelop 不能执行,显示错误 The assembly mscorlib.dll was not found or could not be loaded. 首先要确定mono安装 ...

  10. MySQL计划任务(事件调度器)(Event Scheduler)

    http://www.cnblogs.com/c840136/articles/2388512.html https://dev.mysql.com/doc/refman/5.7/en/events- ...