ios runtime的实际应用,ios runtime运行机制
详细讲解IOS开发和应用的并发调度队列。
类别:iPhone 2011-11-08 18:00
70人阅读评论(0)收藏
报告
IOS开发应用并发调度队列的详细解释是本文介绍的内容。我们几乎可以调度队列来完成线程完成的所有任务。调度比线程代码更简单、更易用、更高效。下面简要介绍调度队列,以及如何在应用程序中使用调度队列执行任务。
1.关于调度队列
的所有调度队列都是先进先出队列。因此,任务在队列中的开始顺序与它们被添加到队列中的顺序相同。GCD自动为我们提供了一些调度队列,我们也可以为特定的目的创建新的队列。
下面是一些可用的调度队列类型以及如何使用它们。
(1)串行队列,也称为私有调度队列,一般用于对特定资源的同步访问。我们可以根据需要创建任意多的串行队列,并且每个串行队列都是并发的。
(2)并行队列,又称全局调度队列。虽然并行队列可以同时执行多个任务,但是任务开始执行的顺序与它们加入队列的顺序相同。我们不能自己创建并行调度队列。只有三个全局并发队列可用。
(3)3)主调度队列是一个全局可用的串行队列,它在line程序的主线程上执行任务。该队列的任务与应用程序主循环要执行的事件源交替执行。因为它运行在应用程序的主线程中,所以主队列经常被用作应用程序的同步点。
2.关于队列的一些技术。
除了调度队列,GCD还提供了一些有用的技术来帮助我们管理代码。
调度组,调度信号量,调度源
3.用积木实现任务
Block objects基于C语言的特点,可以在C和C Objective-C中使用,虽然Block有点类似于函数指针,但它实际上代表了一种底层数据结构,类似于对象,由编译器创建和管理。
block的一个优点是它可以使用自己范围之外的变量。例如,块可以读取其父作用域的变量值,该变量值被复制到块堆的数据结构中。当块被添加到调度队列时,这些值通常是只读的。
块的声明类似于函数指针,除了*被改为。我们可以传递参数来阻止或接收它返回的值。
4.创建和管理调度队列。
(1)获取全局并发调度队列(global concurrent dispatch queues)
系统为每个应用程序提供三个并发调度队列。这三个并发调度队列是全局的,它们只是优先级不同。因为它是全球性的,所以我们不需要创建它。我们只需要使用函数dispath_get_global_queue来获取队列,如下所示:
DISPATCH _ QUEUE _ ta QUEUE=DISPATCH _ get _ global _ QUEUE(DISPATCH _ QUEUE _ PRIORITY _ DEFAULT,0);
除了获取默认的并发队列,还可以通过传递参数dispatch _ queue _ prioity _ high和dispatch _ queue _ prioity _ low来获取高优先级或低优先级。(第二个参数保留用于将来的扩展)
虽然调度队列是一个引用计数对象,但是这里因为队列是全局的,我们不需要去保留或者释放。当我们需要使用它时,我们可以直接调用dispatch _ get _ global _ queue函数。
(2)创建串行调度队列。
当您希望任务以特定顺序执行时,串行队列非常有用。串行队列在同一时间只执行一项任务。我们可以使用串行队列代替锁来保护共享数据。与锁不同,串行队列可以确保任务以可预测的顺序执行。
与并发队列不同,我们必须自己创建和管理串行队列,并且我们可以创建任意数量的串行队列。当我们创建串行队列时,我们应该出于某种目的,例如保护资源或同步应用程序的一些关键行为。
下面的代码描述了如何创建自定义串行队列。dispath_queue_create函数需要两个参数,队列的名称和队列的属性。调试器和性能工具显示队列的名称,帮助我们跟踪任务是如何执行的。队列的属性保留供将来使用,应该为空。
分派_队列_队列;queue=dispatch _ queue _ create( com . example . my queue ,NULL);
除了我自己创建的自定义队列,系统还会自动为我创建一个串行队列,并绑定到应用程序的主线程。以下是获取方法。
(3)在运行时获取公共队列。
GCD提供了一些功能,使我们可以轻松地访问常见的调度队列。
使用dispatch_get_current_queue函数进行调试或测试,以获取当前队列的标识。
使用dispatch_get_main_queue函数获取连接到应用程序主程序的串行调度队列。
(4)调度队列的内存管理
计划是一种参考盘点类型。当我们创建一个串行调度队列时,我们希望释放它。您可以使用dispatch_retain和dispatch_release函数来增加或减少引用计数。
(5)在队列中存储自定义上下文信息
的所有调度对象都允许我们将其与自定义上下文数据相关联,并通过dispatch_set_context和dispatch_get_context函数使用它。系统不会使用我们的自定义数据,我们会在适当的时候分配和发布。
对于队列,上下文数据通常用于存储指向对象或其他数据结构的指针。我们可以在队列终结器函数中释放contextdata。下面将给出一个例子。
(6)为队列提供清理功能。
当我们创建一个串行调度队列时,我们可以将它与一个终结器函数连接起来,以清理队列中需要清理的数据。我们可以使用dispatch_set_finalizer_f函数来设置一个当队列的引用计数为0时会自动调用的函数。使用此函数清理与队列相关的上下文数据。当上下文指针不为空时,将调用此函数。
showsacustomfinalizerfunctionandfunctionthatcreatesqueueandinstallsthatfinalizer。queueusestfinalizerfunctiontoreleasedatastoredinthequeue的ontextpointer。(您将提供给initializedatacontextfunctions和cycleaneupdatacontextfunctions referenced fromthecodearecustomfunctions来初始化和cleanupthecontentsofthedatastructure本身。)contextpointerpassedtothefinalizerfunction包含与队列关联的数据对象。
voidmyFinalizerFunction(void * context){ mydata context * the data=(mydata context *)context;//Cleanupthecontentsofthestructure myCleanUpDataContextFunction(the data);//nowreasesestructureiteself。免费(the data);} dispatch _ queue _ tcreateMyQueue(){ mydata context * data=(mydata context *)malloc(sizeof(mydata context));myInitializeDataContextFunction(数据);//createthequeueandsethecontextdata。dispatch _ queue _ tserial queue=dispatch _ queue _ create( com . example . critical task queue ,NULL);if(串行队列){ dispatch_set_context(串行队列,数据);dispatch _ set _ finalizer _ f(serial queue,myFinalizerFunction);} returnserialQueue}
5.将任务添加到队列中。
(1)向队列添加任务有两种方式,同步或异步。尽可能使用dispatch_async和dispatch_async_f函数,这比同步函数更可取。当我们将一个块对象或函数添加到队列中时,我们无法知道这段代码将在何时执行。
使用这种异步不会阻塞主线程。
尽管尽可能异步添加任务,但有时同步添加任务会防止一些同步错误。函数dispatch_sync和dispatch_sync_f被同步调用。这个函数阻塞主线程的执行,直到指定的任务完成。
下面是一个代码示例:
(2)当任务完成时,执行完成块。
当任务完成时,我们的应用程序需要得到通知并重新合并结果。在传统的异步编程中,我们可能使用回调函数,但是在调度队列中,我们使用完成块。
voidaverage_async(int*data,size_tlen,dispatch_queue_tqueue,void(^block)(int)){//retaintequeueprovidedbytheusertomake//sureitdosenotdisappearbeforethecoompletion//block可以打电话给.dispatch_retain(队列);//Dotheworkonthedefaultconcurrentqueueandthen//调用用户提供得锁定结果.dispatch_async(dispatch_get_global_queue(dispatch_queue_priority_default,0),^{ int avg=average(data,len);dispatch_async(queue,^{block(avg);});//releasetheuser-providedqueuewhendone dispatch _ release(queue);});}
(3)并发的执行循环迭代(循环迭代)
对于为循环,如果每一次的迭代相互都没有影响,可以并发的去执行迭代,使用函数派遣_应用或者分派_应用_f函数。
和正常的循环一样,函数派遣_应用或者分派_应用_f直到所有的循环迭代完成时才返回。
如下代码:
DISPATCH _ QUEUE _ t QUEUE=DISPATCH _ get _ global _ QUEUE(DISPATCH _ QUEUE _ PRIORITY _ DEFAULT,0);dispatch_apply(count,queue,^(size_ti){ printf( % un ,I);});
(4)在主线程上执行任务
我们可以通过调用函数分派_获取_主队列去去得到主线程的调度队列。
小结:详解IOS开发应用之并发调度队列的内容介绍完了,希望通过本文的学习能对你有所帮助
http://mobile.51cto.com/iphone-283323.htm