iBatis中LRU缓存的问题

下载了iBatis的2.3.4版本,部署了自带的jpetstore,开始研究代码,看到iBatis的LRU缓存部分的时候,觉得iBatis的LRU缓存实现的太囧了:用一个HashMap保存要cache的数据,然后又用了一个LinkedList来保存key,每次从缓存中取数据的时候,都要从LinkedList中把这个key删掉,然后又重新添加进去,以此来实现LRU算法。代码如下:

  private int cacheSize;

  private Map cache;

  private List keyList;
  public LruCacheController() {

    this.cacheSize = 100;

    this.cache = Collections.synchronizedMap(new HashMap());

    this.keyList = Collections.synchronizedList(new LinkedList());

  }

public void putObject(CacheModel cacheModel, Object key, Object value) {

    cache.put(key, value);//把我们的数据以key-value的形式存放在缓存中

    keyList.add(key);//同时在keyList中保存key

    if (keyList.size() > cacheSize) {

      try {
        //如果keyList的size大于cacheSize,那么从keyList和cache中移除第一个,从而实现LRU算法
        Object oldestKey = keyList.remove(0);
        cache.remove(oldestKey);
      } catch (IndexOutOfBoundsException e) {}

    }

  }

看完代码想了一下,这样做,只是一味的remove(0),怎么能叫LRU缓存呢?而且,map是不允许有相同的key的,而list是可以的,按照iBatis的做法,会不会最后出现map和list不同步的问题?测试了一下,果然有这个问题。测试方法:

把cacheSize设置为2,然后重复调用putOject:

pubObject(cacheModel,”key1″,value1);

pubObject(cacheModel,”key2″,value2);

pubObject(cacheModel,”key1″,value3);

pubObject(cacheModel,”key1″,value4);

按理说,这时缓存中应该有2个数据:{key1=value4},{key2=value2},可实际结果是缓存中只有{key1=value4},我们丢失了{key2=value2},而且cache和keyList中出现了不同步的现象,cache中是{key1=value4},而keyList中则是[1,1]。

已经把这个问题当bug提交给iBatis了,英文不好,也不知道写的对不对,bug地址:http://issues.apache.org/jira/browse/IBATIS-676

相关文章

*