# 设计高性能线程安全的Java缓存
Java的缓存实现有多种方式, 这里我们将会记录这些实现方式, 熟悉和了解这些方式能让我了解缓存实现注意的细节和各个实现方式的优劣, 这就更能让我轻松在各种场景下选择合适的缓存.(应付缓存导致的bug更是轻松~)
# 使用读写锁实现缓存
读写锁针对读多写少的场景并发性能提升尤为明显
# 代码示例
public class RWLockTest {
static class DataCache {
private static Map<String, String> cache = new HashMap<>();
private static ReadWriteLock rwl = new ReentrantReadWriteLock();
public static String getCache(String key){
//加读锁
rwl.readLock().lock();
//初始化返回结果
String result = null;
try {
//尝试从缓存获取,如果从缓存获取不为空,直接返回结果
if( (result=cache.get(key)) == null){
//即将做数据更新,先释放读锁,加写锁
rwl.readLock().unlock();
rwl.writeLock().lock();
try {
//与外层if形成双重检查,对于更新缓存成功后再拿到`写锁`的线程再做一次校验,避免重复更新
if( (result=cache.get(key)) == null){
//从db获取对应数据,更新到数据库
result = getData4Db(key);
cache.put(key, result);
}
} finally {
//完成数据更新,先释放写锁,再加读锁
rwl.writeLock().unlock();
rwl.readLock().lock();
}
}
} finally {
rwl.readLock().unlock();
}
return result;
}
}
public static String getData4Db(String key){
System.out.println("key:"+key+" 查询数据库");
return key;
}
public static void main(String[] args) {
String result = DataCache.getCache("123");
DataCache.getCache("123");
DataCache.getCache("123");
DataCache.getCache("123");DataCache.getCache("123");DataCache.getCache("123");
DataCache.getCache("222");
DataCache.getCache("123");
System.out.println(result);
}
}
# synchronized实现缓存
# 代码示例
public class SynchronizedTest {
//缓存
private static final Map<String, String> cache = new HashMap<>();
//类锁,可直接用class作锁代替
private static final Object lock = new Object();
//获取缓存的方法
public static String getCache(String key){
String result = null;
//判断缓存内是否存在对应内容
if( (result=cache.get(key))==null){
//不存在所需内容时,直接锁住整个类,改为串行
//这里可以针对key做优化
synchronized (lock){
//经典双重校验
if( (result=cache.get(key))==null){
//从持久化数据源获取内容放入缓存中
//有必要可以对result做判空
cache.put(key, result=getData4Db(key));
}
}
}
return result;
}
//持久化数据源获取内容
private static String getData4Db(String key){
return key;
}
}
# 使用Future优化缓存
# 代码示例