阅读 PINCache 源码
前言: 这里我只介绍一下最核心的地方,至于很多细节并不提及,有兴趣的小伙伴可以查看源码
PINCache
PINCache 是一个 iOS 的三方开源库,提供了缓存的功能。 下面我们了解一下它的实现原理。 学习之前我们可以先了解 5 个东西
项目结构
内存缓存
磁盘缓存
线程安全
清理机制
项目结构
下图展示了 PINCache 架构
PINCache
提供的方法内部都是调用的MemoryCache
或者DiskCache
,其实可以理解为PINCache 类
封装了MemoryCache
和DiskCache
两个类MemoryCache
和DiskCache
也各自提供了自己的Interface
,如果开发者愿意的话 也可以根据自己情况单独调用MemoryCache
和DiskCache
内存缓存
内存缓存是其实就是持有一块内存不释放,然后对其添加要存储的对象,和清理要删除的对象。
优点:
- 读取数据速度快
(因为内存缓存是内存对象)
缺点:
- kill app 就被释放了,无法本地持久化存储。
- 空间小,不能什么都放在内存,内存是寸土寸金的地方。
在 PINCache
中,内存缓存使用的是 NSMutableDictionary
从上面的截图可以看出来, PINCache
内存缓存核心用的是 NSDictionary
对象来进行存储和读取的。
磁盘缓存
磁盘缓存是持久化存储,在 iOS 中一般就是存在沙盒中。
优点:
- 可以持久化存储,App 被 Kill 也无妨。
- 空间大
缺点:
- 访问大数据的速度要慢与内存缓存。
下面是 PINCache
的磁盘缓存的实现逻辑,可以看出来,PINCache 磁盘缓存用了 NSKeyArchiver
和 NSKeyUnarchiver
来实现的对要存储对象的磁盘缓存。
它的存储步骤大致如下(读取相反):
- 用 Key+ 固定 URL 拼接成唯一的 FileURL
- 在把要存的对象 object 通过 NSKeyArchiver 序列化成 data
- 最后将 data 存入 fileURL 的沙盒路径下
线程安全
因为涉及线程安全有很多内容,这里只介绍一下 PINCache
的线程安全是如何处理的。
当程序中开启多线程时,并发的用 写
操作同一个变量的时候,会出现线程不安全,例如 同时 2 个线程同时对变量 A 进行 写
操作,虽然程序里的执行顺序是操作 A 早于操作 B,但是因为是多线程并发,实际执行的时候却是操作 B 早于操作 A,这样你的逻辑就出错了,本来你想的是用操作 B 的值覆盖掉操作 A,现在反过来了,甚至可能会 Crash。
解决这个问题有很多种方法,这里只看下 PINCache 的实现, PINCache
保障线程安全使用的是 条件锁
和 信号量
, 下面是它的实现代码
不懂条件锁和信号量的童鞋可以单独查一下使用和区别。
这里说明一下: 正常情况,我们只需要保证写入就可以了,但是我们看到 PINCache 读取也使用了 Lock,我们大致猜测,可能预防一些比较大的文件,正在写入或者写入一半的时候,这个时候去读取,会导致读取不完整的情况
内存缓存: 信号量
磁盘缓存: 条件锁
清理机制
清理机制这里我就简单带过了 下面介绍几个 PINCache
里面的属性:
- Date: 设置一个过期时间,当缓存内容超过这个日期,会被自动清理掉。
- Cost: 成本代价,未每个存储的 Value 设置一个 Cost,当总的 Cost>LimitCost 的时候会去清理缓存内容来平衡。
- ByteCount: 磁盘缓存的总字节大小,每次缓存的时候都会重新计算更新一次。
剩下一些机制,这里就不再介绍了,大家有兴趣看源码就好了。
总结
我们通过阅读 PINCache
的源码了解到核心的实现原理,如果你之前对缓存框架一头雾水,现在是不是清楚一些了呢。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: 创建常驻线程
下一篇: 彻底找到 Tomcat 启动速度慢的元凶
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论