effective OC2.0 52阅读笔记(六 大中枢派发)+ Objective-C高级编程 (三Grand Central Dispatch)

41 多用派发队列,少用同步锁

总结:当多个线程执行同一份代码时,可能会出现问题,这时有@synchronized(self){}内置同步块。或NSLock对象。然而这只是某种程度上的线程安全,使用串行同步队列(serial sychronization queue).更有效率的方法是使用串行队列同步取方法,异步设置方法。执行异步派发时需要拷贝块。再优化就是改用并发队列,同步取方法,使用栅栏块(只是对并发队列有意义)异步设置方法(读取操作可以并行,但是写入操作必须单独执行)dispatch_barrier_(a)sync(queue,block)。将同步与异步派发结合起来,可以实现与普通加锁机制一样的同步行为。而这么做却不会阻塞执行异步派发的线程。使用同步队列及栅栏块,可以令同步行为更高效。

42 多用GCD,少用performSelector系列方法

总结:performSelector系列方法在内存管理方面容易缺失,它无法确定将要执行的选择子具体是什么,因为ARC编译器也就无法插入适当的内存管理方法。performSelector系列方法所能处理的选择子太过局限了,选择子的返回值类型及发送给方法的参数都受到限制。如果想把任务放在另一个线程上执行,那么最好不要用performSelector系列方法,而是应该把任务封装到块里,用GCD相关方法实现。[self performSelector:@selector(doSomething) withObject:nil afterDelay:5.0]; 改成 dispatch_time_t time = dispatch_time(DIPATCH_TIME_NOW,(int64_t)(5.0*NSEC_PER_SEC));dispatch_after(time,dispatch_get_main_queue(),^(void){[self doSomething]}); dispatch_async(dispatch_get_main_queue(),^{[self doSomething]});

43 掌握GCD(派发队列)及操作队列的使用时机

总结:使用NSOperation及NSOperationQueue的好处有,取消某个操作,制定操作间的依赖关系,制定操作的优先级,重用NSOperation对象。NSNotificationCenter用的就是操作队列。有人说尽可能选择高层的OC方法,只有确有必要的时候才求助于底层。但想要确定哪种方案最佳,还要测试一下性能。

44 通过Dispatch Group机制,根据系统资源状况来执行任务

总结:用法一,将要并发执行的多个任务合为一组,于是调用者就可以知道这些任务何时才能全部执行完毕。dispatch_group_async(group,queue,block); dispatch_group_enter(group) dispatch_group_leave(group)必须成对出现;dispatch_group_wait(group,timeout)等待group执行完毕,阻塞当前线程。dispatch_group_notify(group,queue,block),不阻塞当前线程;一系列任务可以归入一个dispatch group之中。开发者可以在这组任务执行完毕时获得通知。通过dispatch group,可以在并发式派发队列里同时执行多项任务。此时GCD会根据系统资源状况来调度这些并发执行的任务。单个队列搭配标准的异步派发也可以实现dispatch_group同样的效果。dispatch_apply(iterations,queue,block);用的队列可以是并发,也可以是串行,但是dispatch_apply会持续阻塞,知道所有任务都执行完毕为止。所以想要在后台执行任务,应使用group。

45 使用dispatch_once来执行只需运行一次的线程安全代码

总结:此操作是完全线程安全的,且更高效。注意,对于只需执行一次的函数来说,每次调用函数时传入的标记必须都完全相同,所以通常将标记变量声明在static或是global的作用域里。

46 不要使用dispatch_get_current_queue

总结:iOS6.0后弃用此函数。用该方法检测当前队列是不是某个特定队列,试图以此来避免执行同步派发时可能遭遇死锁问题,是错误的。不要把存取方法做成可重入的,而是应该确保同步操作所用的队列绝不会访问属性。并发队列可以用多个线程并行执行多个块。目标队列?队列特有数据:可以把任意数据以键值对的形式关联到队列里。如果根据指定的键获取不到关联数据,那么系统就会沿着层级体系向上查找。直至找到数据或到达根队列为止。

多线程任务取消:

CGD已经加入queue中的block是无法取消的,原生并不支持,也可以,但是需要很复杂的代码,dispatch_suspend只是暂停开启新的未执行的block。NSOperation有取消操已经设定要准备执行的任务,但也不能取消已经开始的任务,但可以通过NSOperation的cancel机制,添加一个外接变量,标记block是否需要取消。在block中及时检测这个外部变量的状态,当发现需要取消时,停止block中的后续操作,释放资源,达到能及时取消block的目的。

下面是一个关于在 dispatch_async 上如何以及何时使用不同的队列类型的快速指导:

  • 自定义串行队列:当你想串行执行后台任务并追踪它时就是一个好选择。这消除了资源争用,因为你知道一次只有一个任务在执行。注意若你需要来自某个方法的数据,你必须内联另一个 Block 来找回它或考虑使用 dispatch_sync。
  • 主队列(串行):这是在一个并发队列上完成任务后更新 UI 的共同选择。要这样做,你将在一个 Block 内部编写另一个 Block 。以及,如果你在主队列调用 dispatch_async 到主队列,你能确保这个新任务将在当前方法完成后的某个时间执行。
  • 并发队列:这是在后台执行非 UI 工作的共同选择。

不知道何时适合使用 dispatch_after ?

  • 自定义串行队列:在一个自定义串行队列上使用 dispatch_after 要小心。你最好坚持使用主队列。
  • 主队列(串行):是使用 dispatch_after 的好选择;Xcode 提供了一个不错的自动完成模版。
  • 并发队列:在并发队列上使用 dispatch_after 也要小心;你会这样做就比较罕见。还是在主队列做这些操作吧。

下面是你何时会——和不会——使用障碍函数的情况:

  • 自定义串行队列:一个很坏的选择;障碍不会有任何帮助,因为不管怎样,一个串行队列一次都只执行一个操作。
  • 全局并发队列:要小心;这可能不是最好的主意,因为其它系统可能在使用队列而且你不能垄断它们只为你自己的目的。
  • 自定义并发队列:这对于原子或临界区代码来说是极佳的选择。任何你在设置或实例化的需要线程安全的事物都是使用障碍的最佳候选。

下面是一个快速总览,关于在何时以及何处使用 dispatch_sync :

  • 自定义串行队列:在这个状况下要非常小心!如果你正运行在一个队列并调用 dispatch_sync 放在同一个队列,那你就百分百地创建了一个死锁。
  • 主队列(串行):同上面的理由一样,必须非常小心!这个状况同样有潜在的导致死锁的情况。
  • 并发队列:这才是做同步工作的好选择,不论是通过调度障碍,或者需要等待一个任务完成才能执行进一步处理的情况。
时间: 2024-10-16 16:36:32

effective OC2.0 52阅读笔记(六 大中枢派发)+ Objective-C高级编程 (三Grand Central Dispatch)的相关文章

effective OC2.0 52阅读笔记(七 系统框架)

47 熟悉系统框架 总结:将代码封装为动态库,并提供接口的头文件,就是框架.平时的三方应用都用静态库(因为iOS应用程序不允许在其中包含动态库),并不是真正的框架,然而也经常视为框架.例如:NSLinguisticTagger可以解析字符串并找到其中的全部名词.动词.代词等.无缝桥接:将CoreFoundation中的C语言数据结构平滑转换为Foundation中的Objective-C对象,也可反向转换.OC编程一个重要特点是,经常需要使用底层的C语言级API,用C语言来实现API的好处是,可

effective OC2.0 52阅读笔记(六 块与大中枢派发)

派发队列:dispatch_queue 操作队列:NSOperationQueue  组:dispathc_group_t 37 理解“块”这一概念 总结:块就是一个值,且自有其相关类型.块的强大之处是,在声明它的范围里,所有变量都可以为其所捕获,如果捕获的变量是对象类型,就会自动保留.且默认情况下被块所捕获的变量,是不可以在块里修改的,若想修改此变量.声明变量的时候可以加上__block.如果将块定义在了OC类的实例方法里,那么除了可以访问类的所有实例变量之外,还可以使用self变量.块总能修

effective OC2.0 52阅读笔记(二)

第二章:对象.消息.运行期 6 理解属性这一概念 总结:OC解决硬编码偏移量问题的做法,一种方案是把实例变量当做一种存储偏移量所用的特殊变量,交由类对象保管,偏移量会在运行期查找,叫做稳固的“应用程序二进制接口”ABI.二种方案是使用存取方法访问实例变量.属性的访问方法由编译器在编译期执行,并且编译器还会自动向类中添加实例变量. eg:如果从core data的框架中的NSManagedObject类里继承一个子类,就需要在运行期动态创建存取方法.因为子类的某些属性不是实例变量,其数据来自后端的

effective OC2.0 52阅读笔记(五 内存管理)

第五章:内存管理 29 理解引用计数 30 以ARC简化引用计数 总结:ARC通过命名约定将内存管理规则标准化.其他编程语言很少像OC这样强调命名.ARC通过设置全局数据结构(此数据结构的具体内容因处理器而异)中的一个标志位,来代替直接调用autorelease和retain.这是ARC所带来的好处.待编译器与运行期组件日臻成熟,还会出现其他的优化技术.CoreFoundation对象不归ARC管理,开发者必须适时调用CFRetain/CFRelease. 31 在dealloc方法中只释放引用

effective OC2.0 52阅读笔记(四 协议与分类)

23 通过委托与数据源协议进行对象间通信 总结:委托模式的常规委托模式中,信息从类Class流向受委托者delegate.数据源模式,信息从数据源datasource流向class.数据源和受委托者可以是两个不同对象.有时候一个可选择方法可能在一个生命期中多次调用,如果每次都检查委托对象是否能响应选择子,那就显得多余了.可以使用位段(bitfield)数据类型将方法响应能力缓存起来. 24 将类的实现代码分散到便于管理的数个分类之中 总结:易于管理,便与调试.将应视为“私有”的方法归入名为Pri

[编写高质量iOS代码的52个有效方法](十)Grand Central Dispatch(GCD)

[编写高质量iOS代码的52个有效方法](十)Grand Central Dispatch(GCD) 参考书籍:<Effective Objective-C 2.0> [英] Matt Galloway 先睹为快 41.多用派发队列,少用同步锁 42.多用GCD,少用performSelector系列方法 43.掌握GCD及操作队列的使用时机 44.通过Dispatch Group机制,根据系统资源状况来执行任务 45.使用dispatch_once来执行只需要运行一次的线程安全代码 46.不

GCD (Grand Central Dispatch) 笔记

GCD (Grand Central Dispatch) 是Apple公司开发的一种技术,它旨在优化多核环境中的并发操作并取代传统多线程的编程模式. 在Mac OS X 10.6和IOS 4.0之后开始支持GCD. 使用GCD的一个理由就是方便.回想一下以前的多线程编程,我们会把异步调用的代码放到另外的一个函数中,并通过NSThread开启新线程来启动这段代码. 这种跳来跳去的流程对于复杂的逻辑简直就是一场灾难.更糟糕的是,调用线程时的环境对异步代码是不可见的,如果我们需要当时的临时变量的话只有

《软件需求十步走》阅读笔记六

本次阅读笔记写一下<软件构造十步走>最后一篇<组织篇>. 本篇共分为四章,分别是建立需求分析体系,需求分析部门的组织结构,需求分析部门的管理工作,需求分析部门的业务工作. 首先是<建立需求分析体系>. 长期以来"轻业务.重技术"的理念根深蒂固,而解决措施是建立一个专业从事软件需求分析的独立部门来承担这项工作.此部门是介于业务部门和技术部门之间的,专门负责对组织自身业务.客户业务.客户对象和竞争对手的研究,然后将其转换成提供给技术部门的软件需求规格说明

假期阅读笔记六

架构之美--企业级应用架构(四) 给我看你的流程图而隐藏你的表,我仍然莫名其妙.如果给我看你的表,那么我将不再需要你的流程图,因为它们太明显了.