GCD和NSOperation多线程技术

 
第一讲  GCD
 
GCD会管理多线程的生命周期
 
GCD底层线程池,队列跟底层线程池之间的交互,底层线程池对线程进行了复用,使用效率要高
 
GCD跟NSThread对比
 
 
  1. 开不开线程,和执行任务的函数有关
- 同步不开
- 异步开
  1. (异步)开几条线程,和队列有关
- 串行队列最多开一条
- 并发队列开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
原文地址:https://www.cnblogs.com/twcblog/p/4764331.html