一个简单的缓存,求指教

小绵羊 2013-12-25 02:58:20
最近给公司网站加了个缓存,用的apache的LRUMap,效果比较好,突发奇想自己想写个简单的缓存试试,下面是代码,自己感觉有点像LRU的意思,但又说不出到底算不算LRU,不知道这个用来做缓存有没有什么问题,或者有没有用这种办法实现的缓存?

import java.util.HashMap;
import java.util.Map;

public class SimpleCache {

private Map enduring = new HashMap();
private Map recycling = new HashMap();

private int maxCapacity;

public SimpleCache(int maxCapacity) {
this.maxCapacity = maxCapacity;
}

public synchronized Object get(String key) {
Object value = enduring.get(key);
if (value == null) {
value = recycling.remove(key);
if (value != null) {
put(key, value);
}
}
return value;
}

public synchronized void put(String key, Object value) {
if (enduring.size() >= maxCapacity) {
if (recycling.size() >= (maxCapacity * 2)) {
recycling.clear();
}
recycling.putAll(enduring);

enduring.clear();
}
enduring.put(key, value);
}

public synchronized void clear() {
enduring.clear();
recycling.clear();
}

@Override
public String toString() {
return enduring.toString() + "\r\n" + recycling.toString();
}
}


...全文
390 17 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
xietingyan 2013-12-26
  • 打赏
  • 举报
回复
也许还可以优化,比如使用更好的同步机制,失效,更新,集群等。
eighthroute 2013-12-26
  • 打赏
  • 举报
回复
最好写成静态的。。。个人认为。。
cnhnxy 2013-12-26
  • 打赏
  • 举报
回复
回贴怎么不加分啊
小绵羊 2013-12-26
  • 打赏
  • 举报
回复
引用 11 楼 huxiweng 的回复:
LRU是Least recently used,最近最少使用。 你这个实现有点简单啊。。。 http://www.cnblogs.com/-OYK/archive/2012/12/05/2803317.html
所以叫SimpleCache,至于我写的这玩意到底算不算的上lru都不好说
tony4geek 2013-12-25
  • 打赏
  • 举报
回复
LRU 是很牛逼/
teemai 2013-12-25
  • 打赏
  • 举报
回复
LRU是Least recently used,最近最少使用。 你这个实现有点简单啊。。。 http://www.cnblogs.com/-OYK/archive/2012/12/05/2803317.html
steely_chen 2013-12-25
  • 打赏
  • 举报
回复
引用 7 楼 x19881216 的回复:
[quote=引用 5 楼 yousteely 的回复:] 虽然没有使用过LRUMap ,可是看楼主的代码有以下建议: 1. new ConcurrentHashMap 会好一点 2. 取的时候不要上锁 3. 存进去的数据设置过期时间,不要以最大容量作为清除的条件。每次取数据的时候判断一下过期了没有,如果过期了就从容器里面移走。 4. 不要使用synchronized锁定方法,可以在方法里面锁定指定对象。我看你的方法全部加了synchronized , 比如有一个线程正在调用get,那么另一个线程就不能调用set了。缓存主要是为了高效,这样做没有起到高效的做用。 纯属个人意见,如有不对大家相互交流。
1.就我写的这个代码来说ConcurrentHashMap 不太适用。 2.取数据如果不上锁多线程环境下会产生数据错误,比如一个线程正在更新这个数据。 3.时间这个我也考虑过,但如果单靠取出数据的时候检查时间会造成Map无限增加,还得用个线程来定时检查(这种我也写了一个)。 4.synchronized的性能其实也没那么差,这个用读写锁改写一下也很方便。 多谢指教了 [/quote] 1,2. ConcurrentHashMap 就能解决多线程存取数据不同步的。 3. 不需要线程定期检查,只要取的时候检查一下并做处理就可以了。时间跟最大容量同时使用应该不错。 4. synchronized 没有锁超时,使用lock 可以指定超时时间,要不然比较容易发生死锁。
aaaabbbccd9876 2013-12-25
  • 打赏
  • 举报
回复
小绵羊 2013-12-25
  • 打赏
  • 举报
回复
引用 4 楼 zzq19860626 的回复:
表示没看懂你的这个cache 给你点建议,你看看mybatis源码里面有缓存,那里面利用了装饰模式,实现了各种缓存,包括lur lur是根据LinkedHashMap实现的,你可以看看。
LRU那个我现在用的就是。现在就是想自个弄个缓存玩玩。
小绵羊 2013-12-25
  • 打赏
  • 举报
回复
引用 5 楼 yousteely 的回复:
虽然没有使用过LRUMap ,可是看楼主的代码有以下建议: 1. new ConcurrentHashMap 会好一点 2. 取的时候不要上锁 3. 存进去的数据设置过期时间,不要以最大容量作为清除的条件。每次取数据的时候判断一下过期了没有,如果过期了就从容器里面移走。 4. 不要使用synchronized锁定方法,可以在方法里面锁定指定对象。我看你的方法全部加了synchronized , 比如有一个线程正在调用get,那么另一个线程就不能调用set了。缓存主要是为了高效,这样做没有起到高效的做用。 纯属个人意见,如有不对大家相互交流。
1.就我写的这个代码来说ConcurrentHashMap 不太适用。 2.取数据如果不上锁多线程环境下会产生数据错误,比如一个线程正在更新这个数据。 3.时间这个我也考虑过,但如果单靠取出数据的时候检查时间会造成Map无限增加,还得用个线程来定时检查(这种我也写了一个)。 4.synchronized的性能其实也没那么差,这个用读写锁改写一下也很方便。 多谢指教了
小绵羊 2013-12-25
  • 打赏
  • 举报
回复
引用 3 楼 lwb314 的回复:
没看明白楼主想干什么。 2个Map把值倒来倒去的。 recycling 貌似是enduring 的备份。 enduring 比初始化值大了就清空,清空之前放入备份的recycling 。 recycling 超过2倍的初始化值就清空,然后把enduring 再备份一下。 最后提供了清空跟toString方法。 额对了,楼主在put和get方法上加上了同步,那为什么不直接用线程安全的Map呢? 楼主你到底想干嘛呢?没接触过LRUMap,不明觉个厉吧! 顺便接点分升星
enduring 区域存放的是常用的数据 recycling 区域存放的是待回收的区域 当enduring 满了以后,将所有数据放入recycling 等待回收。 如果数据被频繁使用即调用get方法获取,那么该数据会从recycling 回到enduring 中,这样可以保证enduring 中的数据是经常被使用或者新放入的数据。 至于那个超出2倍最大容量是为了清除掉长期没有使用的数据。 线程安全的Map在这种情况下不适用。
steely_chen 2013-12-25
  • 打赏
  • 举报
回复
虽然没有使用过LRUMap ,可是看楼主的代码有以下建议: 1. new ConcurrentHashMap 会好一点 2. 取的时候不要上锁 3. 存进去的数据设置过期时间,不要以最大容量作为清除的条件。每次取数据的时候判断一下过期了没有,如果过期了就从容器里面移走。 4. 不要使用synchronized锁定方法,可以在方法里面锁定指定对象。我看你的方法全部加了synchronized , 比如有一个线程正在调用get,那么另一个线程就不能调用set了。缓存主要是为了高效,这样做没有起到高效的做用。 纯属个人意见,如有不对大家相互交流。
张自强 2013-12-25
  • 打赏
  • 举报
回复
表示没看懂你的这个cache 给你点建议,你看看mybatis源码里面有缓存,那里面利用了装饰模式,实现了各种缓存,包括lur lur是根据LinkedHashMap实现的,你可以看看。
  • 打赏
  • 举报
回复
没看明白楼主想干什么。 2个Map把值倒来倒去的。 recycling 貌似是enduring 的备份。 enduring 比初始化值大了就清空,清空之前放入备份的recycling 。 recycling 超过2倍的初始化值就清空,然后把enduring 再备份一下。 最后提供了清空跟toString方法。 额对了,楼主在put和get方法上加上了同步,那为什么不直接用线程安全的Map呢? 楼主你到底想干嘛呢?没接触过LRUMap,不明觉个厉吧! 顺便接点分升星
  • 打赏
  • 举报
回复
缓存也就是数据处理的一种方式。是不是缓存要看你是不是每次都是从目标地址取。如果每次都是从目标地址取,那显然不是缓存。可以测一下看看。
reentrantlock 2013-12-25
  • 打赏
  • 举报
回复
Cache is more complicated than you imagine.Basically,it's unmeaningful to discuss cache without concrete business scenario,such as data size. You'd better make it clear what is the problem your solution will fix. However, for your simple class, 1. How does your application module use this cache? 2. Have you considered the performance issue? Coz I found you always locked the whole cache object,put or get operation.

62,634

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧