一.特点
-
便利性: 类似字典,存取方便.
-
线程安全
-
缓存策略: 可设置存储的最大限制.
二.源码分析
主要属性
open class NSCache<KeyType : AnyObject, ObjectType : AnyObject> : NSObject {
//字典
private var _entries = Dictionary<NSCacheKey, NSCacheEntry<KeyType, ObjectType>>()
//锁
private let _lock = NSLock()
private var _totalCost = 0
//链表
private var _head: NSCacheEntry<KeyType, ObjectType>?
//存储阈值(淘汰策略)
open var totalCostLimit: Int = 0 // limits are imprecise/not strict
open var countLimit: Int = 0 // limits are imprecise/not strict
}
属性作用与特点关系
- **1. _entries **
负责存取.印证了特点1.
- **2._lock **
保证了线程安全,例如查询实现,代码如下:
open func object(forKey key: KeyType) -> ObjectType? {
var object: ObjectType?
let key = NSCacheKey(key)
_lock.lock()
if let entry = _entries[key] {
object = entry.value
}
_lock.unlock()
return object
}
- 3. _head,totalCostLimit,countLimit,totalCost
存储的实现代码如下:
//调用API
open func setObject(_ obj: ObjectType, forKey key: KeyType) {
setObject(obj, forKey: key, cost: 0)
}
//内部实现
open func setObject(_ obj: ObjectType, forKey key: KeyType, cost g: Int) {
//cost为obj存储资源大小,默认为0.
let g = max(g, 0)
let keyRef = NSCacheKey(key)
_lock.lock()
let costDiff: Int
//检测是否key对应有obj
//有
if let entry = _entries[keyRef] {
//资源大小对比
costDiff = g - entry.cost
entry.cost = g
entry.value = obj
if costDiff != 0 {
//先删除再存储
remove(entry)
insert(entry)
}
} else {
//无: 直接存储
let entry = NSCacheEntry(key: key, value: obj, cost: g)
_entries[keyRef] = entry
insert(entry)
costDiff = g
}
//缓存处理:
_totalCost += costDiff
//如果totalCostLimit> 0, 如果totalCostLimit超出,则执行删除操作.
var purgeAmount = (totalCostLimit > 0) ? (_totalCost - totalCostLimit) : 0
while purgeAmount > 0 {
if let entry = _head {
delegate?.cache(unsafeDowncast(self, to:NSCache<AnyObject, AnyObject>.self), willEvictObject: entry.value)
_totalCost -= entry.cost
purgeAmount -= entry.cost
remove(entry) // _head will be changed to next entry in remove(_:)
_entries[NSCacheKey(entry.key)] = nil
} else {
break
}
}
//类似的,如果countLimit超出,则执行删除操作.
var purgeCount = (countLimit > 0) ? (_entries.count - countLimit) : 0
while purgeCount > 0 {
if let entry = _head {
delegate?.cache(unsafeDowncast(self, to:NSCache<AnyObject, AnyObject>.self), willEvictObject: entry.value)
_totalCost -= entry.cost
purgeCount -= 1
//删除
remove(entry) // _head will be changed to next entry in remove(_:)
_entries[NSCacheKey(entry.key)] = nil
} else {
break
}
}
_lock.unlock()
}
三.缓存策略
缓存策略太简单,适应不了复杂需求.
四.优秀的缓存策略:
- 自动计算存储对象的实际容量.
- 按时间,先清除最早的内容.
- 按使用频率,先清除使用频率低的内容.