【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>
package liurong.driver.cache;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
/**
*
* @desc 缓存模板
*
* @author liurong
*
* @date 2019年12月27日
*/
public abstract class CacheTemplate<T> {
private static final ConcurrentHashMap<String, ReentrantLock> CACHE_LOCK = new ConcurrentHashMap<String, ReentrantLock>();
/**
* 获取数据(内部已经防止缓存击穿)
*
* @param key
* @return
*/
public T getData(String key) {
T cacheData = getCache(key);
if (cacheData == null) {
cacheData = get(key);
}
return cacheData;
}
/**
* 防止缓存击穿
*
* @param key
* @return
*/
public T get(String key) {
ReentrantLock LOCK = getLock(key);
if (LOCK.tryLock()) {// 只允许一个线程穿透缓存,查询DB
try {
T cache = getCache(key);// 再次查询缓存,提高缓存命中率
if (cache == null) {
// 设置缓存
setCache(key, getDB(key));
} else {
return cache;
}
} finally {
LOCK.unlock();
}
}
try {
LOCK.lock();
return getCache(key);
} finally {
LOCK.unlock();
// 清空锁
CACHE_LOCK.remove(key);
}
}
/**
* 获取锁
*
* @param key
* @return
*/
private static ReentrantLock getLock(String key) {
ReentrantLock LOCK = CACHE_LOCK.putIfAbsent(key, new ReentrantLock());
if (LOCK == null) {// 第一次设置必然为null,所以这里防止第一次获取为null
LOCK = CACHE_LOCK.get(key);
}
return LOCK;
}
/**
* 设置缓存
*
* @param key
* @param value
* @return
*/
public abstract void setCache(String key, T value);
/**
* 从缓存获取
*
* @param key
* @return
*/
public abstract T getCache(String key);
/**
* 从DB获取
*
* @param key
* @return
*/
public abstract T getDB(String key);
}
package liurong.driver.cache;
import java.util.concurrent.ConcurrentHashMap;
public class AddressCache extends CacheTemplate<String> {
// 这里可以使本地缓存,也可以是nosql缓存
public static final ConcurrentHashMap<String, String> CACHE_DATA = new ConcurrentHashMap<String, String>();
@Override
public void setCache(String key, String value) {
CACHE_DATA.put(key, value);
}
@Override
public String getCache(String key) {
return CACHE_DATA.get(key);
}
@Override
public String getDB(String key) {
return "自己实现从DB获取数据";
}
}
package liurong.driver.cache;
public class AddressCacheTest {
public static AddressCache addressCache = new AddressCache();
static {
addressCache.setCache("1", "1");
addressCache.setCache("2", "2");
addressCache.setCache("3", "3");
}
public static void main(String[] args) {
System.out.println(addressCache.getData("1"));
System.out.println(addressCache.getData("abc"));
}
}
来源:oschina
链接:https://my.oschina.net/u/2937247/blog/3148325