- 浏览: 1316771 次
- 性别:
- 来自: 成都
文章分类
- 全部博客 (471)
- 原创文章 (4)
- Database (84)
- J2SE (63)
- Web (26)
- Javascript (30)
- Lucene (11)
- os (13)
- 算法 (8)
- Webservice (1)
- Open projects (18)
- Hibernate (18)
- Spring (15)
- Css (2)
- J2ee (2)
- 综合技术 (18)
- 安全管理 (13)
- PatternsInJava (27)
- NIO (5)
- Ibatis (2)
- 书籍收藏 (1)
- quartz (7)
- 并发编程 (15)
- oracle问题 (2)
- ios (60)
- coco2d-iphone (3)
- C++ (6)
- Zookeeper (2)
- golang (4)
- animation (2)
- android (1)
最新评论
-
dandingge123:
【引用】限制UITextField输入长度的方法 -
qja:
...
对List顺序,逆序,随机排列实例代码 -
安静听歌:
现在在搞这个,,,,,哎~头都大了,,,又freemarker ...
通用大型网站页面静态化解决方案(一) -
springdata-jpa:
java quartz定时任务demo教程源代码下载,地址:h ...
Quartz 配置参考 -
马清天:
[b][/b][list][*]引用[u][/u][/list ...
通用大型网站页面静态化解决方案(一)
基本概念和Dispatch Queue
- 博客分类:
- ios
转自 http://www.dreamingwish.com/dream-2012/of-of-of-of-gcd-introduced-1-basic-concepts-in-and-the-dispatch-queue.html
什么是GCD?
Grand Central Dispatch或者GCD,是一套低层API,提供了一种新的方法来进行并发程序编写。从基本功能上讲,GCD有点像NSOperationQueue,他们都允许程序将任务切分为多个单一任务然后提交至工作队列来并发地或者串行地执行。GCD比之NSOpertionQueue更底层更高效,并且它不是Cocoa框架的一部分。
除了代码的平行执行能力,GCD还提供高度集成的事件控制系统。可以设置句柄来响应文件描述符、mach ports(Mach port 用于 OS X上的进程间通讯)、进程、计时器、信号、用户生成事件。这些句柄通过GCD来并发执行。
GCD的API很大程度上基于block,当然,GCD也可以脱离block来使用,比如使用传统c机制提供函数指针和上下文指针。实践证明,当配合block使用时,GCD非常简单易用且能发挥其最大能力。
你可以在Mac上敲命令“man dispatch”来获取GCD的文档。
为何使用?
GCD提供很多超越传统多线程编程的优势:
- 易用: GCD比之thread跟简单易用。由于GCD基于work unit而非像thread那样基于运算,所以GCD可以控制诸如等待任务结束、监视文件描述符、周期执行代码以及工作挂起等任务。基于block的血统导致它能极为简单得在不同代码作用域之间传递上下文。
- 效率: GCD被实现得如此轻量和优雅,使得它在很多地方比之专门创建消耗资源的线程更实用且快速。这关系到易用性:导致GCD易用的原因有一部分在于你可以不用担心太多的效率问题而仅仅使用它就行了。
- 性能: GCD自动根据系统负载来增减线程数量,这就减少了上下午切换以及增加了计算效率。
Dispatch Objects
尽管GCD是纯c语言的,但它被组建成面向对象的风格。GCD对象被称为dispatch object。Dispatch object像Cocoa对象一样是引用计数的。使用dispatch_release和dispatch_retain函数来操作dispatch object的引用计数来进行内存管理。但主意不像Cocoa对象,dispatch object并不参与垃圾回收系统,所以即使开启了GC,你也必须手动管理GCD对象的内存。
Dispatch queues 和 dispatch sources(后面会介绍到)可以被挂起和恢复,可以有一个相关联的任意上下文指针,可以有一个相关联的任务完成触发函数。可以查阅“man dispatch_object”来获取这些功能的更多信息。
Dispatch Queues
GCD的基本概念就是dispatch queue。dispatch queue是一个对象,它可以接受任务,并将任务以先到先执行的顺序来执行。dispatch queue可以是并发的或串行的。并发任务会像NSOperationQueue那样基于系统负载来合适地并发进行,串行队列同一时间只执行单一任务。
GCD中有三种队列类型:
- The main queue: 与主线程功能相同。实际上,提交至main queue的任务会在主线程中执行。main queue可以调用dispatch_get_main_queue()来获得。因为main queue是与主线程相关的,所以这是一个串行队列。
- Global queues: 全局队列是并发队列,并由整个进程共享。进程中存在三个全局队列:高、中(默认)、低三个优先级队列。可以调用dispatch_get_global_queue函数传入优先级来访问队列。
-
用户队列: 用户队列 (GCD并不这样称呼这种队列, 但是没有一个特定的名字来形容这种队列,所以我们称其为用户队列) 是用函数
dispatch_queue_create
创建的队列. 这些队列是串行的。正因为如此,它们可以用来完成同步机制, 有点像传统线程中的mutex。
创建队列
要使用用户队列,我们首先得创建一个。调用函数dispatch_queue_create就行了。函数的第一个参数是一个标签,这纯是为了debug。Apple建议我们使用倒置域名来命名队列,比如“com.dreamingwish.subsystem.task”。这些名字会在崩溃日志中被显示出来,也可以被调试器调用,这在调试中会很有用。第二个参数目前还不支持,传入NULL就行了。
提交 Job
向一个队列提交Job很简单:调用dispatch_async函数,传入一个队列和一个block。队列会在轮到这个block执行时执行这个block的代码。下面的例子是一个在后台执行一个巨长的任务:
1
2
3
4
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
[ self goDoSomethingLongAndInvolved ];
NSLog ( @ "Done doing something long and involved" );
});
|
dispatch_async
函数会立即返回, block会在后台异步执行。
当然,通常,任务完成时简单地NSLog个消息不是个事儿。在典型的Cocoa程序中,你很有可能希望在任务完成时更新界面,这就意味着需要在主线程中执行一些代码。你可以简单地完成这个任务——使用嵌套的dispatch,在外层中执行后台任务,在内层中将任务dispatch到main queue:
1
2
3
4
5
6
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
[ self goDoSomethingLongAndInvolved ];
dispatch_async(dispatch_get_main_queue(), ^{
[textField setStringValue : @ "Done doing something long and involved" ];
});
});
|
还有一个函数叫dispatch_sync,它干的事儿和dispatch_async相同,但是它会等待block中的代码执行完成并返回。结合 __block类型修饰符,可以用来从执行中的block获取一个值。例如,你可能有一段代码在后台执行,而它需要从界面控制层获取一个值。那么你可以使用dispatch_sync简单办到:
1
2
3
4
5
6
7
8
|
__block NSString *stringValue;
dispatch_sync(dispatch_get_main_queue(), ^{
// __block variables aren't automatically retained
// so we'd better make sure we have a reference we can keep
stringValue = [[textField stringValue ] copy ];
});
[stringValue autorelease ];
// use stringValue in the background now
|
我们还可以使用更好的方法来完成这件事——使用更“异步”的风格。不同于取界面层的值时要阻塞后台线程,你可以使用嵌套的block来中止后台线程,然后从主线程中获取值,然后再将后期处理提交至后台线程:
dispatch_queue_t bgQueue = myQueue; dispatch_async(dispatch_get_main_queue(), ^{ NSString *stringValue = [[[textField stringValue] copy] autorelease]; dispatch_async(bgQueue, ^{ // use stringValue in the background now }); });
取决于你的需求,myQueue可以是用户队列也可以使全局队列。
不再使用锁(Lock)
用户队列可以用于替代锁来完成同步机制。在传统多线程编程中,你可能有一个对象要被多个线程使用,你需要一个锁来保护这个对象:
NSLock *lock;
访问代码会像这样:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
- ( id )something
{
id localSomething;
[lock lock ];
localSomething = [[something retain ] autorelease ];
[lock unlock ];
return localSomething;
}
- ( void )setSomething:( id )newSomething
{
[lock lock ];
if (newSomething != something)
{
[something release ];
something = [newSomething retain ];
[ self updateSomethingCaches ];
}
[lock unlock ];
}
|
使用GCD,可以使用queue来替代:
dispatch_queue_t queue;
要用于同步机制,queue必须是一个用户队列,而非全局队列,所以使用usingdispatch_queue_create
初始化一个。然后可以用dispatch_async
或者 dispatch_sync
将共享数据的访问代码封装起来:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
- ( id )something
{
__block id localSomething;
dispatch_sync(queue, ^{
localSomething = [something retain ];
});
return [localSomething autorelease ];
}
- ( void )setSomething:( id )newSomething
{
dispatch_async(queue, ^{
if (newSomething != something)
{
[something release ];
something = [newSomething retain ];
[ self updateSomethingCaches ];
}
});
}
|
值得注意的是dispatch queue是非常轻量级的,所以你可以大用特用,就像你以前使用lock一样。
现在你可能要问:“这样很好,但是有意思吗?我就是换了点代码办到了同一件事儿。”
实际上,使用GCD途径有几个好处:
-
平行计算: 注意在第二个版本的代码中,
-setSomething:是怎么使用dispatch_async的。调用
-setSomething:会立即返回,然后这一大堆工作会在后台执行。如果updateSomethingCaches是一个很费时费力的任务,且调用者将要进行一项处理器高负荷任务,那么这样做会很棒。
- 安全: 使用GCD,我们就不可能意外写出具有不成对Lock的代码。在常规Lock代码中,我们很可能在解锁之前让代码返回了。使用GCD,队列通常持续运行,你必将归还控制权。
- 控制: 使用GCD我们可以挂起和恢复dispatch queue,而这是基于锁的方法所不能实现的。我们还可以将一个用户队列指向另一个dspatch queue,使得这个用户队列继承那个dispatch queue的属性。使用这种方法,队列的优先级可以被调整——通过将该队列指向一个不同的全局队列,若有必要的话,这个队列甚至可以被用来在主线程上执行代码。
- 集成: GCD的事件系统与dispatch queue相集成。对象需要使用的任何事件或者计时器都可以从该对象的队列中指向,使得这些句柄可以自动在该队列上执行,从而使得句柄可以与对象自动同步。
总结
现在你已经知道了GCD的基本概念、怎样创建dispatch queue、怎样提交Job至dispatch queue以及怎样将队列用作线程同步。接下来我会向你展示如何使用GCD来编写平行执行代码来充分利用多核系统的性能^ ^。我还会讨论GCD更深层的东西,包括事件系统和queue targeting。
发表评论
-
ios 声音合成
2013-08-18 13:20 1242http://stackoverflow.com/ques ... -
__bridge,__bridge_retained和__bridge_transfer的意思,区别与使用 20 三
2012-12-24 01:41 1649使用ARC能帮我们减轻不少内存管理方面的负担,尤其是对用 ... -
CAAnimation
2012-12-23 01:09 2307CAAnimation采用了CAMediaTi ... -
UIViewAnimation动画与Core Animation的CATransition类动画
2012-12-23 01:06 2703使用UIView类函数实现://U ... -
GCD实战2:资源竞争
2012-12-23 01:04 1557转自http://www.dreamingwish.co ... -
GCD实战一:使用串行队列实现简单的预加载
2012-12-22 17:10 2828转自 http://www.dreamingwish.c ... -
GCD介绍(四): 完结
2012-12-22 17:08 1334转自 http://www.dreamingwish.c ... -
GCD介绍(三): Dispatch Sources
2012-12-22 17:07 1603转自 http://www.dreamingwish.com/ ... -
GCD介绍(二): 多核心的性能
2012-12-22 17:05 1156转自http://www.dreamingwish.co ... -
Best Audio Format for iPhone Audio Programming
2012-12-19 16:26 2512I had never done audio p ... -
LAME 是一个开源的MP3解码编码工具
2012-12-19 13:09 8506MP3 Encoding * 编码MP3文件必须按如下 ... -
sqlite3中的数据类型
2012-12-10 21:37 1274(转)http://www.cnblogs.com/kfqco ... -
ios随机数,and()、random()、arc4random()
2012-11-15 11:06 4696原文:http://bj007.blog.51cto.c ... -
IPHONE GIF 播放的方式
2012-10-11 18:30 1418转 http://blog.csdn.net/zltia ... -
在新线程中使用NSTimer
2012-10-11 18:21 1557转自 http://blog.csdn.net/sjzs ... -
Creating an iPhone Daemon – Part 5
2012-09-02 15:29 1509Creating an iPhone Daemon – ... -
Creating an iPhone Daemon – Part 4
2012-09-02 15:28 1384Creating an iPhone Daemon – ... -
Creating an iPhone Daemon – Part 3
2012-09-02 15:25 1480This is part three of the bl ... -
Creating an iPhone Daemon – Part 2
2012-09-02 15:24 1226Here is part two of the blog ... -
Creating an iPhone Daemon – Part 1
2012-09-02 15:23 1137So I thought I would start t ...
相关推荐
ios demo,dispatch_async,DISPATCH_QUEUE_CONCURRENT,多任务并发执行,自动创建多线
1. dispatch_queue_t queue = dispatch_queue_create(“com.dispatch.serial”, DISPATCH_QUEUE_SERIAL); //生成一个串行队列,队列中的block按照先进先出(FIFO)的顺序去执行,实际上为单线程
异步和同步的栅栏函数都有以下特点: 1、通过dispatch_barrier_(a)sync添加的block会等待前边所有的block执行完(不包括回调)才执行。 2、在其后添加的block会在dispatch_barrier_(a)sync添加的block执行完之后...
此文档介绍了GCD的基本概念及核心方法,Dispatch Queue,Dispatch Source等等特性。
dispatch_queue_t queue = dispatch_queue_create("com.gcd-dispatch_group_async(gro
DISPATCH
Dispatch IDS for IExplorer Dispatch Events
Apple的Grand Central Dispatch(GCD)的防锈包装。 GCD是任务并行性的一种实现,它允许将任务提交到用于Apple的Grand Central Dispatch(GCD)的Rust包装器的...该应用程序的主队列是串行的,可以通过Queue进行访问:
异步OC 用Objective-C重写... 代替熟悉的GCD语法: dispatch_async (dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0 ), ^{ NSLog ( @" A: This is run on the background " ); dispatch_async ( dis
以上两种方式都是模拟任务block内为异步操作的情况,方式一先执行的dispatch_group_notify里的代码,后执行的dispatch_group_async里的任务代码,这与我们的初衷相违背。如果任务block内为同步操作时,则无论哪种...
connectify dispatch 4.0完美破解版
QueueDispatcher为Rails3中/ ...这将为模型Task和TaskQueues创建数据库迁移。 如果从1.5.1之前的版本更新queue_dispatcher,则必须使用以下命令来更新您的迁移: 用 rails g queue_dispatcher:migration --skip 这
关于grasshopper的基础练习,dispatch案例的电池资源。
当需要在后台 queue 中定期执行任务的时候,使用 Dispatch Source Timer 要比使用 NSTimer 更加自然,也更加高效(无需在 main queue 和后台 queue 之前切换)。下面将详细给大家介绍关于Dispatch Source Timer的...
ios demo,主队列,异步调度,手动创建线程,detachNewThreadSelector dispatch_get_main_queue
双击“Installer”安装Connectify Dispatch...复制Crack目录中的dispatch.dll和web文件夹到软件安装目录中的\plugins\dispatch目录覆盖同名文件。 复制Crack目录中的connectify.exe文件到安装程序目录覆盖同名文件。
、NSRunLoop 和 Dispatch Queue> 一文示例源代码
Connectify Dispatch Incl. Hotspot Pro. Multiple Connections, Maximum Speed For the first time, you can connect to the coffee shop Wi-Fi and your 4G mobile device simultaneously, using both Internet...
通过它你可以将不同的宽带连接在一起,就好象把几根不同的绳子拧在一起,以获得更坚固的效果,和绳子不同的是,它可以给更快的网速,这个对于蹭网用户绝对是一款不可多得的好工具,实际效果如何,需要各位自行测试了...
spark-dispatch.zip