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);
- iOS开发——GCD多线程详解
GCD多线程详解 1. 什么是GCD Grand Central Dispatch 简称(GCD)是苹果公司开发的技术,简单来说,GCD就是iOS一套解决多线程的机制,使用GCD能够最大限度简化多线程 ...
- GCD多线程的一个全面的题目
GCD多线程的一个全面的题目
- [Xcode 实际操作]八、网络与多线程-(22)使用GCD多线程技术异步下载图片
目录:[Swift]Xcode实际操作 本文将演示如何使用使用GCD多线程技术异步下载图片. Grand Central Dispatch(GCD) 是 Apple 开发的一个多核编程的较新的解决方法 ...
- Object-C关于GCD多线程的使用
```objc1 使用Crearte函数创建的并发队列和全局并发队列的主要区别: 1)全局并发队列在整个应用程序中本身是默认存在的并且对应有高优先级.默认优先级.低优先级和后台优先级一共四个并发队列, ...
- iOS开发——多线程篇——NSOperation(基于GCD多线程编程),下载图片并合成新图片
一.NSOperation的基本概念1.简介NSOperation的作用配合使用NSOperation和NSOperationQueue也能实现多线程编程 NSOperation和NSOperatio ...
- GCD 多线程 初探
GCD编程的核心就是dispatch队列,dispatch block的执行最终都会放进某个队列中去进行,它类似NSOperationQueue但更复杂也更强大,并且可以嵌套使用.所以说,结合bloc ...
- ios 使用GCD 多线程 教程
什么是GCD Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法.该方法在Mac OS X 10.6雪豹中首次推出,并随后被引入到了iOS4.0中.GCD ...
- ios开发:GCD多线程
ios有三种多线程编程技术,分别是NSThread,Cocoa NSOperation和GCD,GCD全称Grand Central Dispatch 是Apple开发的一个多核编程的解决方法,在iO ...
- GCD多线程
GCD本质线程自动管理指令包 GCD优点: 1.GCD 本身自带有线程锁的效果,能通过推迟昂贵计算任务并在后台运行它们来改善应用的响应性能. 2.GCD 提供了更易于使用的并发模型(效果方面类似于对锁 ...
- iOS——GCD多线程
1> 概述 Grand Central Dispatch (GCD)是Apple开发的一种多核编程技术.主要用于优化应用程序以支持多核处理器以及其他对称多处理系统. GCD提供函数实现多线程开发 ...
随机推荐
- hdu 1877 又一版 A+B
又一版 A+B Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub ...
- iOS开发核心语言Objective C —— 所有知识点总结
C和OC对比 OC中主要开发在什么平台上的应用程序?答:可以使用OC开发Mac OS X平台和iOS平台的应用程序 OC中新增关键字大部分是以什么开头?答:OC中新增关键字大部分是以@开头 OC中新增 ...
- Umbraco中的权限体系结构
分为管理用户体系,和成员用户体系,也就是 Users(用户)和Members(成员). 2.1. Users(用户) 用户是对功能操作权限定义的,首先看一下所有Action的Permissions: ...
- Java快捷键
Ctrl+1 快速修复(最经典的快捷键,就不用多说了)Ctrl+D: 删除当前行 Ctrl+Alt+↓ 复制当前行到下一行(复制增加)Ctrl+Alt+↑ 复制当前行到上一行(复制增加)Alt+↓ 当 ...
- Activity详解
Activity是android应用的重要组成单元之一(另外3个是Service,BroadcastReceiver和ContentProvider).实际应用包含了多个Activity,不同的Act ...
- VM使用标准交换机
1.新建模板: 网卡选择“未连接”,此处看不到“标准交换机”选项
- PHP strlen() 函数
定义和用法 strlen() 函数返回字符串的长度. 语法 strlen(string) 参数 描述 string 必需.规定要检查的字符串. 例子 <?php echo strlen(&quo ...
- C#-将控件动态添加到选项卡页tablepage
tabPage1.Controls.Add(new Button()); 实例: Button cp = new Button(); cp.text="test";cp.Click ...
- Codeforces Round #321 (Div. 2) E. Kefa and Watch 线段树hash
E. Kefa and Watch Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/580/prob ...
- UIView上添加了一个按钮和一个单击手势的事件相应,互相不影响的处理方法。。
tapGesture.delegate = self; - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shoul ...