用system.currenttimemillis()实现缓存过期需同时存储值和写入时间戳,读取时通过当前时间减去时间戳判断是否超过expiremillis,过期则移除并返回null;每次写入必须同步更新时间戳,注意时间回拨风险及线程安全。

用 System.currentTimeMillis() 实现缓存过期,核心就是记录写入时间,并在读取时对比当前时间与过期时长。
记录写入时间戳
缓存数据时,不仅要存值,还要一并保存写入时刻的时间戳(毫秒)。例如用 Map 存储时,可封装成简单对象或用嵌套结构:
- 推荐方式:自定义缓存项类,含
value和timestamp字段 - 简易方式:用
Map<string pair long>></string>(需自行实现或借助AbstractMap.SimpleEntry) - 避免只存值、另用独立 map 存时间戳——易不同步、难维护
读取时判断是否过期
获取缓存前,先取出对应的时间戳,计算是否超过设定的过期时长(如 5 分钟 = 5 × 60 × 1000 毫秒):
- 过期条件:
System.currentTimeMillis() - timestamp > expireMillis - 若已过期,应移除该缓存项并返回 null 或触发重新加载
- 注意:不要用
>=,避免因毫秒精度导致刚写入就判定为过期
写入时更新时间戳
每次 put 缓存,必须同步更新时间戳。尤其注意以下场景:
- 缓存穿透/击穿后回填数据,要重置时间戳,否则沿用旧时间会提前过期
- 刷新缓存(比如定时预热)也必须更新时间戳,否则无效
- 多线程环境下,若缓存操作非线程安全,需加锁或使用
ConcurrentHashMap配合原子操作
注意事项与局限
这种基于 System.currentTimeMillis() 的方案轻量但有边界:
- 依赖系统时钟,若发生时间回拨(如 NTP 校准),可能导致缓存误判过期或不过期
- 不支持 LRU/LFU 等淘汰策略,仅靠时间驱动,内存占用需自行控制
- 高并发下频繁调用
currentTimeMillis()开销极小,但频繁判断仍建议减少无谓检查(如加个“是否启用过期”开关)











