Skip to content

Instantly share code, notes, and snippets.

@pooooch
Created April 23, 2012 03:55
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pooooch/2468759 to your computer and use it in GitHub Desktop.
Save pooooch/2468759 to your computer and use it in GitHub Desktop.
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
/**
* 一种本地缓存的无锁实现思路
* 适用场景:预先知道的需要缓存的一批数据,比如卖家品牌授权,馆信息,达人信息
* 数据更新不太频繁,定时更新或者更新由自己手动控制
*/
public abstract class AbstractLocalCache<K, V> {
/**
* 使用volatile保证不同线程对更新立即可见
*/
private volatile Map<K, V> cache = new HashMap<K, V>();
/**
*访问缓存
*/
public V get(K key) {
System.out.println(cache);
return cache.get(key);
}
/**
* 在bean初始化时就载入缓存
* <bean id='xxx' init-method='init' />
* 当然如果load过程非常缓慢,会影响bean的初始化完成,进而影响应用启动
* 如果是这种情形,考虑改写init方法,另起线程执行load,代价就是可能开始时访问缓存不命中,但不会引起抛出NullPoint
*/
public void init() {
load(true);
}
/**
* 无锁的更新缓存:build完成后,将cache指向new map
* 可以使用时间调度框架达到定时更新缓存目的,比如一天一次
* 可以通过jsp直接调用方法,达到手动更新缓存目的
* keepWhenNull参数是为了当build结果返回null时,根据自身需求选择保留之前缓存,还是清空缓存
*/
public void load(boolean keepWhenNull) {
Map<K, V> tmp = build();
if (tmp != null) {
cache = tmp;
} else if (!keepWhenNull) {
cache = new HashMap<K, V>();
}
}
/**
* build新缓存数据
* 根据数据具体位置具体实现,form local file,from db ,from tair...
* build方法无法直接操作到cache,这样可以保证cache即使是非线程安全的hashmap也不会造成问题
* 可以根据自己需求,返回不同的map实现
*/
public abstract Map<K, V> build();
@SuppressWarnings("unchecked")
public void put1(K key, V value) {
Map<K, V> tmp;
try {
tmp = cache.getClass().newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
return;
} catch (IllegalAccessException e) {
e.printStackTrace();
return;
}
tmp.put(key, value);
for (Entry<K, V> entry : cache.entrySet()) {
tmp.put(entry.getKey(), entry.getValue());
}
cache = tmp;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment