本文目录导读:

我来通过一个简单但完整的Java案例,展示如何实现内存缓存。
基础版本 - 简单HashMap缓存
import java.util.concurrent.ConcurrentHashMap;
public class SimpleCache<K, V> {
private final ConcurrentHashMap<K, V> cache = new ConcurrentHashMap<>();
public void put(K key, V value) {
cache.put(key, value);
}
public V get(K key) {
return cache.get(key);
}
public void remove(K key) {
cache.remove(key);
}
public void clear() {
cache.clear();
}
public boolean containsKey(K key) {
return cache.containsKey(key);
}
public int size() {
return cache.size();
}
}
带过期时间的缓存
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
public class ExpiringCache<K, V> {
private static class CacheEntry<V> {
private final V value;
private final long expirationTime;
private final long createdTime;
public CacheEntry(V value, long ttlMillis) {
this.value = value;
this.createdTime = System.currentTimeMillis();
this.expirationTime = createdTime + ttlMillis;
}
public boolean isExpired() {
return System.currentTimeMillis() > expirationTime;
}
public V getValue() {
return value;
}
public long getRemainingTime() {
long remaining = expirationTime - System.currentTimeMillis();
return Math.max(0, remaining);
}
}
private final ConcurrentHashMap<K, CacheEntry<V>> cache = new ConcurrentHashMap<>();
private final long defaultTtlMillis;
public ExpiringCache(long defaultTtlMillis) {
this.defaultTtlMillis = defaultTtlMillis;
}
public ExpiringCache(long ttl, TimeUnit unit) {
this.defaultTtlMillis = unit.toMillis(ttl);
}
public void put(K key, V value) {
put(key, value, defaultTtlMillis);
}
public void put(K key, V value, long ttlMillis) {
cache.put(key, new CacheEntry<>(value, ttlMillis));
}
public V get(K key) {
CacheEntry<V> entry = cache.get(key);
if (entry == null) {
return null;
}
if (entry.isExpired()) {
cache.remove(key);
return null;
}
return entry.getValue();
}
public void remove(K key) {
cache.remove(key);
}
public void clear() {
cache.clear();
}
public int size() {
// 清理过期条目后再返回大小
removeExpiredEntries();
return cache.size();
}
private void removeExpiredEntries() {
cache.entrySet().removeIf(entry -> entry.getValue().isExpired());
}
}
完整的内存缓存实现 - 支持最大容量和LRU淘汰
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class MemoryCache<K, V> {
private static class CacheEntry<V> {
private final V value;
private final long expirationTime;
public CacheEntry(V value, long expirationTime) {
this.value = value;
this.expirationTime = expirationTime;
}
public boolean isExpired() {
return System.currentTimeMillis() > expirationTime;
}
}
private final int maxSize;
private final long defaultTtlMillis;
private final LinkedHashMap<K, CacheEntry<V>> cache;
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public MemoryCache(int maxSize, long defaultTtlMillis) {
this.maxSize = maxSize;
this.defaultTtlMillis = defaultTtlMillis;
// 使用LinkedHashMap实现LRU淘汰
this.cache = new LinkedHashMap<K, CacheEntry<V>>(16, 0.75f, true) {
@Override
protected boolean removeEldestEntry(Map.Entry<K, CacheEntry<V>> eldest) {
return size() > MemoryCache.this.maxSize;
}
};
}
public void put(K key, V value) {
put(key, value, defaultTtlMillis);
}
public void put(K key, V value, long ttlMillis) {
long expirationTime = System.currentTimeMillis() + ttlMillis;
CacheEntry<V> entry = new CacheEntry<>(value, expirationTime);
lock.writeLock().lock();
try {
cache.put(key, entry);
System.out.println("缓存添加成功 - Key: " + key + ", TTL: " + ttlMillis + "ms");
} finally {
lock.writeLock().unlock();
}
}
public V get(K key) {
lock.readLock().lock();
try {
CacheEntry<V> entry = cache.get(key);
if (entry == null) {
return null;
}
if (entry.isExpired()) {
lock.readLock().unlock();
lock.writeLock().lock();
try {
cache.remove(key);
System.out.println("缓存已过期 - Key: " + key);
return null;
} finally {
lock.writeLock().unlock();
lock.readLock().lock();
}
}
return entry.value;
} finally {
lock.readLock().unlock();
}
}
public void remove(K key) {
lock.writeLock().lock();
try {
cache.remove(key);
System.out.println("缓存已删除 - Key: " + key);
} finally {
lock.writeLock().unlock();
}
}
public void clear() {
lock.writeLock().lock();
try {
cache.clear();
System.out.println("缓存已清空");
} finally {
lock.writeLock().unlock();
}
}
public int size() {
lock.readLock().lock();
try {
return cache.size();
} finally {
lock.readLock().unlock();
}
}
public void cleanExpiredEntries() {
lock.writeLock().lock();
try {
cache.entrySet().removeIf(entry -> entry.getValue().isExpired());
System.out.println("过期缓存清理完成");
} finally {
lock.writeLock().unlock();
}
}
public Map<K, V> getAll() {
lock.readLock().lock();
try {
Map<K, V> result = new java.util.HashMap<>();
for (Map.Entry<K, CacheEntry<V>> entry : cache.entrySet()) {
if (!entry.getValue().isExpired()) {
result.put(entry.getKey(), entry.getValue().value);
}
}
return result;
} finally {
lock.readLock().unlock();
}
}
}
使用示例
import java.util.concurrent.TimeUnit;
public class CacheExample {
public static void main(String[] args) throws InterruptedException {
// 创建缓存:最大容量100,默认过期时间5秒
MemoryCache<String, String> cache = new MemoryCache<>(100, 5000);
// 1. 基本使用
System.out.println("=== 基本使用 ===");
cache.put("user1", "张三");
cache.put("user2", "李四");
System.out.println("获取user1: " + cache.get("user1")); // 输出: 张三
System.out.println("缓存大小: " + cache.size()); // 输出: 2
// 2. 过期测试
System.out.println("\n=== 过期测试 ===");
cache.put("temp", "临时数据", 2000); // 2秒过期
System.out.println("立即获取: " + cache.get("temp")); // 输出: 临时数据
Thread.sleep(3000); // 等待3秒
System.out.println("3秒后获取: " + cache.get("temp")); // 输出: null(已过期)
// 3. 自定义过期时间
System.out.println("\n=== 自定义过期时间 ===");
cache.put("session1", "session数据", 10000); // 10秒过期
cache.put("config", "配置信息", TimeUnit.MINUTES.toMillis(30)); // 30分钟过期
// 4. 删除和清空
System.out.println("\n=== 删除操作 ===");
cache.put("delete_test", "将被删除");
cache.remove("delete_test");
System.out.println("删除后获取: " + cache.get("delete_test")); // 输出: null
// 5. 模拟LRU淘汰
System.out.println("\n=== LRU淘汰测试 ===");
MemoryCache<Integer, String> smallCache = new MemoryCache<>(3, 60000);
smallCache.put(1, "A");
smallCache.put(2, "B");
smallCache.put(3, "C");
smallCache.get(1); // 访问key 1
smallCache.get(2); // 访问key 2
smallCache.put(4, "D"); // 添加新元素,最久未使用的key 3将被淘汰
System.out.println("获取key 1: " + smallCache.get(1)); // 输出: A
System.out.println("获取key 3: " + smallCache.get(3)); // 输出: null(被淘汰)
System.out.println("缓存大小: " + smallCache.size()); // 输出: 3
// 6. 批量清理过期缓存
System.out.println("\n=== 清理过期缓存 ===");
cache.cleanExpiredEntries();
// 7. 获取所有有效缓存
System.out.println("\n所有有效缓存: ");
cache.getAll().forEach((key, value) ->
System.out.println(key + " -> " + value));
// 8. 清空缓存
cache.clear();
System.out.println("\n清空后大小: " + cache.size()); // 输出: 0
}
}
带统计功能的缓存
public class StatisticsCache<K, V> extends MemoryCache<K, V> {
private long hitCount = 0;
private long missCount = 0;
private long totalPuts = 0;
public StatisticsCache(int maxSize, long defaultTtlMillis) {
super(maxSize, defaultTtlMillis);
}
@Override
public V get(K key) {
V value = super.get(key);
if (value != null) {
hitCount++;
} else {
missCount++;
}
return value;
}
@Override
public void put(K key, V value, long ttlMillis) {
super.put(key, value, ttlMillis);
totalPuts++;
}
public void printStatistics() {
System.out.println("=== 缓存统计 ===");
System.out.println("总存储次数: " + totalPuts);
System.out.println("命中次数: " + hitCount);
System.out.println("未命中次数: " + missCount);
System.out.println("命中率: " +
String.format("%.2f", (double) hitCount / (hitCount + missCount) * 100) + "%");
System.out.println("当前大小: " + size());
}
}
这个案例展示了内存缓存的完整实现,包括:
- 基本功能:存储、获取、删除
- 过期策略:支持TTL(生存时间)
- 淘汰策略:LRU(最近最少使用)
- 线程安全:使用读写锁保证并发安全
- 性能优化:使用ConcurrentHashMap
- 统计功能:命中率等性能监控
你可以根据实际需求选择合适的实现方案。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播