我设计了一个牛逼的本地缓存!
点击上方 好好学java ,选择 星标 公众号
重磅资讯、干货,第一时间送达
重磅资讯、干货,第一时间送达
今日推荐:硬刚一周,3W字总结,一年的经验告诉你如何准备校招!
个人原创100W+访问量博客:点击前往,查看更多
个人原创100W+访问量博客:点击前往,查看更多
作者:ksfzhaohui
http://dwz.win/Ws4
考虑点
1.数据结构
2.对象上限
3.清除策略
4.过期时间
5.线程安全
6.简明的接口
7.是否持久化
8.阻塞机制
如何实现
1.数据结构
Map<Object, Object> cache = new ConcurrentHashMap<Object, Object>()Mybatis使用HashMap本身是非线程安全的,所以可以看到起内部使用了一个SynchronizedCache用来包装,保证线程的安全性;
2.对象上限
3.清除策略
LRU :Least Recently
Used的缩写最近最少使用,移除最长时间不被使用的对象;常见的使用LinkedHashMap来实现,也是很多本地缓存默认使用的策略;
FIFO :先进先出,按对象进入缓存的顺序来移除它们;常见使用队列Queue来实现;
LFU :Least Frequently
Used的缩写大概也是最近最少使用的意思,和LRU有点像;区别点在LRU的淘汰规则是基于访问时间,而LFU是基于访问次数的;可以通过HashMap并且记录访问次数来实现;
SOFT :软引用基于垃圾回收器状态和软引用规则移除对象;常见使用SoftReference来实现;
WEAK :弱引用更积极地基于垃圾收集器状态和弱引用规则移除对象;常见使用WeakReference来实现;
4.过期时间
被动删除 :每次进行get/put操作的时候都会检查一下当前key是否已经过期,如果过期则删除,类似如下代码:
if (System.currentTimeMillis() - lastClear > clearInterval) {
clear();
}
5.线程安全
public synchronized void putObject(Object key, Object object) {
...省略...
}
@Override
public synchronized Object getObject(Object key) {
...省略...
}
6.简明的接口
public interface Cache {
String getId();
void putObject(Object key, Object value);
Object getObject(Object key);
Object removeObject(Object key);
void clear();
int getSize();
ReadWriteLock getReadWriteLock();
}
public interface Cache<K, V> {
V getIfPresent(@CompatibleWith("K") Object key);
V get(K key, Callable extends V> loader) throws ExecutionException;
ImmutableMapgetAllPresent(Iterable> keys) ;
void put(K key, V value);
void putAll(Map extends K, ? extends V> m);
void invalidate(@CompatibleWith("K") Object key);
void invalidateAll(Iterable> keys);
void invalidateAll();
long size();
CacheStats stats();
ConcurrentMapasMap() ;
void cleanUp();
}
7.是否持久化
diskPersistent="false" //是否持久化磁盘缓存
8.阻塞机制
public class Memoizerl<A, V> implements Computable<A, V> {
private final Map> cache = new ConcurrentHashMap>();
private final Computable c;
public Memoizerl(Computable c) {
this.c = c;
}
@Override
public V compute(A arg) throws InterruptedException, ExecutionException {
while (true) {
Futuref = cache.get(arg);
if (f == null) {
Callableeval = new Callable () {
@Override
public V call() throws Exception {
return c.compute(arg);
}
};
FutureTaskft = new FutureTask (eval);
f = cache.putIfAbsent(arg, ft);
if (f == null) {
f = ft;
ft.run();
}
try {
return f.get();
} catch (CancellationException e) {
cache.remove(arg, f);
}
}
}
}
}
总结
推荐文章
原创电子书
历时整整一年总结的 Java 面试 + Java 后端技术学习指南,这是本人这几年及校招的总结,各种高频面试题已经全部进行总结,按照章节复习即可,已经拿到了大厂offer。
原创思维导图
扫码或者微信搜 程序员的技术圈子 回复 面试 领取原创电子书和思维导图。
评论