第一讲 GCD
GCD会管理多线程的生命周期
GCD底层线程池,队列跟底层线程池之间的交互,底层线程池对线程进行了复用,使用效率要高
GCD跟NSThread对比
- (异步)开几条线程,和队列有关
- 串行队列最多开一条
- 并发队列开N条,具体条数由GCD决定!
主队列:
主队列同步会死锁:
注意主队列同步也能够不死锁,具体状况具体对待
主队列异步: 不会开启线程,在主线程中执行,可是主队列中的任务须要等待主线程中任务执行完毕以后才能执行
barrier阻塞:
会先循环执行完下载完成(全部异步执行完以后再执行barrier的block中代码),同一线程中顺序执行
注意:dispatch_barrier_async
必须使用自定义队列,不然执行效果和全局队列一致
dispatch_once 只执行一次的代码,注意单例中的static可以保证在block中局部变量能够记录保存在静态区,不会被销毁
dispatch_once是同步的,是线程安全的, dispatch_once内部也有一把锁,这把锁的性能很高
dispatch_group 调度组 dispatch_group_notify 异步的
dispatch_after 延迟操做- 异步执行的 所以在dispatch_after的block中执行的任务是在子线程中执行
第二讲 NSOperation
iOS8以后,GCD底层的线程池特别慷慨,只要要就给,能够开不少条线程
NSOperation是iOS2.0推出的,GCD是iOS4.0推出的
ARC是Xcode4.2推出的
NSInvocationOperation和NSBlockOperation的使用(都是异步并发执行的)
线程间通信:
NSOperation和GCD的对比:
NSOperation设置最大并发数 setMaxConcurrentOperationCount
暂停继续(队列的挂起状态),挂起的是队列,不会影响正在执行的操做
取消,暂停和继续
依赖关系
异步下载图片
在异步下载图片的时候的问题及解决:
当异步下载图片以后,因为blockOperation是异步下载的,当返回cell的时候image还未下载下来,因此因为cell的imageView懒加载,并未显示图片,当点击或者上下滚动才显示
解决办法:占位图片提早设置imageView,固定imageView的大小
可是此时又有问题,占位图片太大,下载图片小,因此一开始显示占位图片大点击cell以后显示小的下载图片
解决办法:自定义cell,设置好imageView的大小,能够完整显示占位图片和下载图片
然而还有问题,此时图片每次滚动都会下载,而且当网速不一样会致使图片错位,缘由:好比第一个cell的图片下载很快,第九个以后就很慢,当第一个cell进入缓存池以后,第十个cell会进行cell复用,此时cell的图片下载很慢,图片还未下载完,当在往上滚动的时候,第一个cell会复用第十个 cell,因为第一个cell图片下载快,因此显示以后过几秒会再下载显示第十个cell未下载完的图片,从而发生图片错位的现象。
解决办法:利用MVC模式,在模型中定义图片属性,将图像异步保存在模型中,并刷新当前行调用数据源方法,在cell中判断模型是否有图片,显示模型中存储的图像。这样同时解决了不断从网络下载的问题
操做缓冲池:
为何须要操做缓冲池?由于在下载网络图片的时候,当网络很慢,而用户快速滑动,好比第一个cell的图片没有下载完,因而会在建立一个操做添加到队列中,这样会形成资源的浪费
下载结束,清除操做缓冲
图像缓冲池的引入
因为模型内保存图片跟模型绑定的很紧,当接收到内存警告的时候很差释放,因此须要引入图像缓冲池,相似于操做缓冲池,用url做为key用字典缓冲
layoutsubviews方法的调用
内存警告清理缓冲池
实现沙盒缓存见SDWebImage