在C++项目开发中,本地缓存能够有效减少重复计算或重复IO操作,提升程序运行效率。给缓存添加过期时间可以避免过期数据长期占用内存,保证缓存数据的有效性。结合std::chrono时间库和定时器任务可以很方便地实现带过期时间的本地缓存功能。

核心设计思路
实现带过期时间的本地缓存需要解决三个核心问题:缓存项的存储结构、过期时间的判断、过期缓存的清理。我们可以设计一个缓存项结构,同时存储缓存值和对应的过期时间点,使用std::chrono来获取当前时间并计算过期时间。定时器任务可以定期触发,遍历所有缓存项,清理已经过期的条目。
缓存项结构设计
缓存项需要包含存储的值和过期时间点,这里使用模板来支持不同类型的缓存值:
#include <chrono>
#include <mutex>
#include <unordered_map>
#include <functional>
#include <thread>
#include <atomic>
// 缓存项结构,存储值和过期时间点
template <typename T>
struct CacheItem {
T value; // 缓存的值
std::chrono::steady_clock::time_point expire_time; // 过期时间点
CacheItem(const T& val, std::chrono::steady_clock::time_point exp)
: value(val), expire_time(exp) {}
};
缓存类的整体定义
缓存类需要支持写入、读取、清理操作,同时需要保证线程安全,使用互斥锁保护共享数据:
template <typename Key, typename Value>
class ExpirableCache {
private:
std::unordered_map<Key, CacheItem<Value>> cache_map; // 存储缓存的映射表
std::mutex cache_mutex; // 互斥锁,保证线程安全
std::thread clean_thread; // 清理线程
std::atomic<bool> running{true}; // 缓存运行状态
int clean_interval_ms; // 清理间隔,单位毫秒
public:
// 构造函数,传入清理间隔
explicit ExpirableCache(int interval_ms = 1000) : clean_interval_ms(interval_ms) {
// 启动清理线程
clean_thread = std::thread(&ExpirableCache::clean_expired_task, this);
}
// 析构函数,停止清理线程
~ExpirableCache() {
running = false;
if (clean_thread.joinable()) {
clean_thread.join();
}
}
// 写入缓存,传入键、值、过期时间(毫秒)
void put(const Key& key, const Value& value, int ttl_ms) {
std::lock_guard<std::mutex> lock(cache_mutex);
auto expire_time = std::chrono::steady_clock::now() + std::chrono::milliseconds(ttl_ms);
cache_map[key] = CacheItem<Value>(value, expire_time);
}
// 读取缓存,返回是否读取成功
bool get(const Key& key, Value& result) {
std::lock_guard<std::mutex> lock(cache_mutex);
auto it = cache_map.find(key);
if (it == cache_map.end()) {
return false;
}
// 判断缓存是否过期
auto now = std::chrono::steady_clock::now();
if (it->second.expire_time < now) {
// 过期则删除并返回失败
cache_map.erase(it);
return false;
}
result = it->second.value;
return true;
}
private:
// 清理过期缓存的定时器任务
void clean_expired_task() {
while (running) {
// 等待清理间隔
std::this_thread::sleep_for(std::chrono::milliseconds(clean_interval_ms));
if (!running) break;
clean_expired();
}
}
// 执行清理过期缓存的逻辑
void clean_expired() {
std::lock_guard<std::mutex> lock(cache_mutex);
auto now = std::chrono::steady_clock::now();
for (auto it = cache_map.begin(); it != cache_map.end(); ) {
if (it->second.expire_time < now) {
it = cache_map.erase(it);
} else {
++it;
}
}
}
};
使用示例
下面是一个简单的使用示例,演示缓存的写入、读取和过期效果:
#include <iostream>
#include <string>
int main() {
// 创建缓存实例,清理间隔设置为1秒
ExpirableCache<std::string, int> cache(1000);
// 写入缓存,键为"test_key",值为100,过期时间500毫秒
cache.put("test_key", 100, 500);
int value;
if (cache.get("test_key", value)) {
std::cout << "第一次读取成功,值为:" << value << std::endl;
} else {
std::cout << "第一次读取失败" << std::endl;
}
// 等待600毫秒,让缓存过期
std::this_thread::sleep_for(std::chrono::milliseconds(600));
if (cache.get("test_key", value)) {
std::cout << "第二次读取成功,值为:" << value << std::endl;
} else {
std::cout << "第二次读取失败,缓存已过期" << std::endl;
}
return 0;
}
注意事项
- 使用
std::chrono::steady_clock而不是std::chrono::system_clock,因为steady_clock是单调时钟,不会受系统时间调整的影响,更适合计算时间间隔。 - 缓存操作都加了互斥锁,保证多线程环境下的线程安全,如果单线程使用可以去掉锁相关逻辑提升性能。
- 清理线程会在缓存实例析构时自动停止,避免线程资源泄漏。
- 可以根据实际需求调整清理间隔,间隔太短会频繁触发清理,间隔太长会导致过期缓存占用内存时间过长。
C++std::chrono定时器任务本地缓存修改时间:2026-07-16 07:54:25