答案:Java中实现线程安全的LRU缓存可通过继承LinkedHashMap并同步访问,或用ConcurrentHashMap与双向链表手动实现;前者简单但性能低,后者结合读写锁提升并发效率,适用于高并发场景。
在Java中实现线程安全的LRU(Least Recently Used)缓存,核心是结合双向链表和哈希表,并确保多线程环境下的操作安全。可以通过继承 LinkedHashMap 或手动实现一个支持并发访问的数据结构来完成。
Java 的 LinkedHashMap 提供了维护插入或访问顺序的能力,通过重写 removeEldestEntry 方法可以轻松实现 LRU 策略。为了保证线程安全,需要用 Collections.synchronizedMap 包装或直接使用同步代码块。
示例代码:
public class SynchronizedLRUCacheextends LinkedHashMap { private final int capacity; public SynchronizedLRUCache(int capacity) { super(capacity, 0.75f, true); // true 表示按访问顺序排序 this.capacity = capacity; } @Override protected boolean removeEldestEntry(Map.Entry eldest) { return size() > capacity; } // 必须外部同步访问 private final Object lock = new Object(); public V get(K key) { synchronized (lock) { return super.get(key); } } public V put(K key, V value) { synchronized (lock) { return super.put(key, value); } } }
注意:虽然 LinkedHashMap 本身不是线程安全的,但通过对象锁保护 get 和 put 操作,可实现基本的线程安全。
更高效且灵活的方式是自己维护一个双向链表与 ConcurrentHashMap 配合,这样能避免锁整个 map,提高并发性能。
关键点:
示例结构:
class Node{ K key; V value; Node prev; Node next; // 构造函数... }
缓存类中包含:
get 操作流程:
put 操作流程:
为提升性能,可考虑:
例如:
private final ReadWriteLock lock = new ReentrantReadWriteLock(); private final Lock readLock = lock.readLock(); private final Lock writeLock = lock.writeLock();
get 方法使用 readLock,put 使用 writeLock。
基本上就这些。选择哪种方式取决于性能要求和使用场景。简单场景可用 synchronized 包装 LinkedHashMap;高并发环境推荐手动实现并配合并发容器和锁机制。