派发队列:dispatch_queue 操作队列:NSOperationQueue  组:dispathc_group_t

37 理解“块”这一概念

总结:块就是一个值,且自有其相关类型。块的强大之处是,在声明它的范围里,所有变量都可以为其所捕获,如果捕获的变量是对象类型,就会自动保留。且默认情况下被块所捕获的变量,是不可以在块里修改的,若想修改此变量。声明变量的时候可以加上__block。如果将块定义在了OC类的实例方法里,那么除了可以访问类的所有实例变量之外,还可以使用self变量。块总能修改实例变量,所以在声明时也无需加_block。不过,如果通过读取或写入操作捕获了实例变量(这里所指的并不单单指用self,所以说只要是用到了实例变量就会捕捉self?),那么也会自动把self变量一并捕获,因为实例变量与self所指代的实例是关联在一起的。定义块的时候其所占内存区域是分配到栈中的(栈块)。此时可以给块对象发送copy消息以拷贝之。这样的话,可以把块从栈复制到堆(堆块)。全局块,不捕捉任何状态,全部信息都能在编译期运行。_NSGlobalStack,_NSStackBlock,_NSMallocStack。MRC下用_block修饰不会引起循环引用,ARC下用_block修饰就会引起循环引用,但是用_weak或_weakSelf就不会。

38 为常用的块类型创建typedef

总结:每个块都具备其“固有类型”(inherent type),这个由块所接受的参数及其返回值组成。可以为同一个块签名定义多个类型别名。

39 用handler块降低代码分散程度

总结:当某些代码必须运行在特定线程上,可以用handler来实现。设置api时如果用到了handler块,可以增加一个参数,使调用者可通过此参数来决定应该把块安排在哪个队列上执行。

40 用块引用其所属对象时不要出现保留环

总结:一定要找个适当的时机解除保留环,而不能把责任推给API的调用者。block中引用实例变量_xxx并不直接保留该变量,而是保留self。但若引用变量则是直接保留该变量。

番外:NSString *a = @“hello”;a为常量变量(存储在内存中的常量区)。@“hello”为常量。不加__block会引用常量的地址(浅拷贝)。加__block类型block会去引用常量变量的地址。

NSString *str = @"hello";

NSLog(@"hello======%p",str);

void (^print)(void) = ^{

NSLog(@"block=str======%p",str);

};

str = @"hello1";

NSLog(@"hello1======%p",str);

print();

block会拷贝变量内容到自己的栈内存上,以执行时可以调用。但并不是重新申请内存。

对于NSMallocBlock的copy只是增加一次其引用。

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

effective OC2.0 52阅读笔记(六 块与大中枢派发)的更多相关文章

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

    47 熟悉系统框架 总结:将代码封装为动态库,并提供接口的头文件,就是框架.平时的三方应用都用静态库(因为iOS应用程序不允许在其中包含动态库),并不是真正的框架,然而也经常视为框架.例如:NSLin ...

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

    第五章:内存管理 29 理解引用计数 30 以ARC简化引用计数 总结:ARC通过命名约定将内存管理规则标准化.其他编程语言很少像OC这样强调命名.ARC通过设置全局数据结构(此数据结构的具体内容因处 ...

  3. effective OC2.0 52阅读笔记(二 对象、消息、运行期)

    第二章:对象.消息.运行期 6 理解属性这一概念 总结:OC解决硬编码偏移量问题的做法,一种方案是把实例变量当做一种存储偏移量所用的特殊变量,交由类对象保管,偏移量会在运行期查找,叫做稳固的“应用程序 ...

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

    23 通过委托与数据源协议进行对象间通信 总结:委托模式的常规委托模式中,信息从类Class流向受委托者delegate.数据源模式,信息从数据源datasource流向class.数据源和受委托者可 ...

  5. effective OC2.0 52阅读笔记(三 接口与API设计)

    第三章:接口与API设计 15 用前缀避免命名空间冲突 总结:避免重名符号错误的唯一办法是变相实现命名空间.为所有符号都加上命名前缀.类和分类都应加三字前缀.注意类实现文件中的纯C函数及全局变量,是算 ...

  6. effective OC2.0 52阅读笔记(一 熟悉Objective-C)

    第一章:熟悉Objective-C 1 了解objective-c语言的起源 总结:OC为C语言添加了面向对象的特性,是其超集.采用动态绑定的消息结构而非函数调用,也就是说,要在运行时才检查对象类型及 ...

  7. 云时代架构阅读笔记六——Java内存模型详解(二)

    承接上文:云时代架构阅读笔记五——Java内存模型详解(一) 原子性.可见性.有序性 Java内存模型围绕着并发过程中如何处理原子性.可见性和有序性这三个特征来建立的,来逐个看一下: 1.原子性(At ...

  8. 论文阅读笔记六:FCN:Fully Convolutional Networks for Semantic Segmentation(CVPR2015)

    今天来看一看一个比较经典的语义分割网络,那就是FCN,全称如题,原英文论文网址:https://people.eecs.berkeley.edu/~jonlong/long_shelhamer_fcn ...

  9. 论文阅读笔记六十五:Enhanced Deep Residual Networks for Single Image Super-Resolution(CVPR2017)

    论文原址:https://arxiv.org/abs/1707.02921 代码: https://github.com/LimBee/NTIRE2017 摘要 以DNN进行超分辨的研究比较流行,其中 ...

随机推荐

  1. 【笔记5】用pandas实现矩阵数据格式的推荐算法 (基于物品的协同)

    ''' 基于物品的协同推荐 矩阵数据 说明: 1.修正的余弦相似度是一种基于模型的协同过滤算法.我们前面提过,这种算法的优势之 一是扩展性好,对于大数据量而言,运算速度快.占用内存少. 2.用户的评价 ...

  2. mysql集群数据一致性校验

    目前,mysql在互联网行业使用地如火如荼,很多大型网站都在使用MySQL数据库,通过搭建mysql主备集群,实现高性能,高可用的存储方案.mysql集群的共同特性是通过复制来实现主备间的同步,保证主 ...

  3. linux下vi命令大全

    进入vi的命令vi filename :打开或新建文件,并将光标置于第一行首vi +n filename :打开文件,并将光标置于第n行首vi + filename :打开文件,并将光标置于最后一行首 ...

  4. 调用webapi 错误:使用 HTTP 谓词 POST 向虚拟目录发送了一个请求,而默认文档是不支持 GET 或 HEAD 以外的 HTTP 谓词的静态文件。的解决方案

    第一次调用webapi出错如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http:// ...

  5. 【跟着子迟品 underscore】如何优雅地写一个『在数组中寻找指定元素』的方法

    Why underscore (觉得这部分眼熟的可以直接跳到下一段了...) 最近开始看 underscore.js 源码,并将 underscore.js 源码解读 放在了我的 2016 计划中. ...

  6. C#基础系列——小话泛型

    前言:前面两章介绍了C#的两个常用技术:C#基础系列——反射笔记 和 C#基础系列——Attribute特性使用 .这一章来总结下C#泛型技术的使用.据博主的使用经历,觉得泛型也是为了重用而生的,并且 ...

  7. 通过CAGradientLayer制作渐变色效果(转)

    转载自:http://blog.it985.com/7986.html 看了极客学院的视频之后写的一篇博客,觉得不错,还是作为笔记使用. 简单介绍一下CAGradientLayer吧. Gradien ...

  8. float,double和decimal类型

    float:浮点型,含字节数为4,32bit,数值范围为-3.4E38~3.4E38(7个有效位) double:双精度实型,含字节数为8,64bit数值范围-1.7E308~1.7E308(15个有 ...

  9. 菜鸟初识python request属性及方法说明

    if  request.REQUEST.has_key('键值'): HttpRequest对象的属性 参考: 表 H-1. HttpRequest对象的属性 属性 描述 path 表示提交请求页面完 ...

  10. SQL 优化tips

    1. 陷阱, 1)几个表进行join,然后过滤 等价于 2)分别过滤为小表后,再join? 并不完全.2)确实比1)效率高,但要注意一些NULL值过滤.否则2)得到的结果比1)多