昨天晚上花了一个多小时完成了我的大轮子的第二部分:缓存
今天中午利用休息时间写了测试用例,还算很顺利的,哈哈。

代码如下:

package com.jiehoo.core;

class CacheInfo {
    String key;

    long create;

    long lastAccess;

    long used;

    CacheInfo(String key) {
        this.key = key;
        create = System.currentTimeMillis();
    }

    void touch() {
        lastAccess = System.currentTimeMillis();
        used++;
    }
}

package com.jiehoo.core;

import java.util.Comparator;

public class FIFOComparator implements Comparator {

    public int compare(Object o1, Object o2) {
        CacheInfo info1 = (CacheInfo) o1;
        CacheInfo info2 = (CacheInfo) o2;
        if (info1.create < info2.create) {
            return -1;
        } else if (info1.create > info2.create) {
            return 1;
        } else {
            return 0;
        }
    }
}

package com.jiehoo.core;

import java.util.Comparator;

public class LFUComparator implements Comparator {

    public int compare(Object o1, Object o2) {
        CacheInfo info1 = (CacheInfo) o1;
        CacheInfo info2 = (CacheInfo) o2;
        if (info1.used < info2.used) {
            return -1;
        } else if (info1.used > info2.used) {
            return 1;
        } else {
            return 0;
        }
    }
}

package com.jiehoo.core;

import java.util.Comparator;

public class LRUComparator implements Comparator {

    public int compare(Object o1, Object o2) {
        CacheInfo info1 = (CacheInfo) o1;
        CacheInfo info2 = (CacheInfo) o2;
        if (info1.lastAccess < info2.lastAccess) {
            return -1;
        } else if (info1.lastAccess > info2.lastAccess) {
            return 1;
        } else {
            return 0;
        }
    }
}

package com.jiehoo.core;

import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class CacheManager {
    public static final int LFU = 0;

    public static final int LRU = 1;

    public static final int FIFO = 2;

    public static final int UNLIMIT = 3;

    public static final int DEFAULT_MAX_CAPACITY = 100;

    private static final Map managers = new HashMap();

    private static Comparator lfuComparator = new LFUComparator();

    private static Comparator lruComparator = new LRUComparator();

    private static Comparator fifoComparator = new FIFOComparator();

    private int type;

    private int maxCapacity;

    private Map cache;

    private List cacheInfos;

    private Map keyMap;

    private CacheManager(int type, int maxCapacity) {
        this.type = type;
        cache = new HashMap(maxCapacity);
        keyMap = new HashMap(maxCapacity);
        if (type == UNLIMIT) {
            this.maxCapacity = Integer.MAX_VALUE;
        } else {
            this.maxCapacity = maxCapacity;
        }
        cacheInfos = new LinkedList();
    }

    public static synchronized CacheManager getCacheManager(String name) {
        return getCacheManager(name, UNLIMIT, DEFAULT_MAX_CAPACITY);
    }

    public static synchronized CacheManager getCacheManager(String name, int type) {
        return getCacheManager(name, type, DEFAULT_MAX_CAPACITY);
    }

    public static synchronized CacheManager getCacheManager(String name, int type, int maxCapacity) {
        CacheManager cacheManager = (CacheManager) managers.get(name);
        if (cacheManager == null) {
            cacheManager = new CacheManager(type, maxCapacity);
            managers.put(name, cacheManager);
        }
        return cacheManager;
    }

    public synchronized void put(String key, Object object) {
        if (cache.size() >= maxCapacity) {
            removeFirst();
        }
        Object old = cache.put(key, object);
        if (old == null) {
            CacheInfo cacheInfo = new CacheInfo(key);
            cacheInfos.add(cacheInfo);
            keyMap.put(key, cacheInfo);
        }
    }

    private void removeFirst() {
        switch (type) {
        case LFU:
            Collections.sort(cacheInfos, lfuComparator);
            break;
        case LRU:
            Collections.sort(cacheInfos, lruComparator);
            break;
        case FIFO:
            Collections.sort(cacheInfos, fifoComparator);
            break;
        }
        CacheInfo cacheInfo = (CacheInfo) cacheInfos.get(0);
        keyMap.remove(cacheInfo.key);
        cache.remove(cacheInfo.key);
        cacheInfos.remove(0);
    }

    public synchronized Object get(String key) {
        Object result = cache.get(key);
        if (result != null) {
            CacheInfo cacheInfo = (CacheInfo) keyMap.get(key);
            cacheInfo.touch();
        }
        return result;
    }

}

测试用例:
package com.jiehoo.core;

import junit.framework.TestCase;

public class TestCacheManager extends TestCase {

    public void testUnlimitCacheManager() {
        CacheManager cacheManager = CacheManager.getCacheManager("UnlimitCacheManager", CacheManager.UNLIMIT);
        for (int i = 0; i < CacheManager.DEFAULT_MAX_CAPACITY + 100; i++) {
            cacheManager.put("key" + i, new Object());
        }
        assertNotNull(cacheManager.get("key0"));
    }

    public void testFIFOCacheManager() {
        CacheManager cacheManager = CacheManager.getCacheManager("FIFOCacheManager", CacheManager.FIFO, 100);
        for (int i = 0; i < 120; i++) {
            cacheManager.put("key" + i, new Object());
        }
        assertNull(cacheManager.get("key0"));
        assertNull(cacheManager.get("key19"));
        assertNotNull(cacheManager.get("key20"));
        assertNotNull(cacheManager.get("key119"));
    }

    public void testLRUCacheManager() throws Exception {
        CacheManager cacheManager = CacheManager.getCacheManager("LRUCacheManager", CacheManager.LRU, 10);
        for (int i = 0; i < 10; i++) {
            cacheManager.put("key" + i, new Object());
        }
        for (int i = 0; i < 10; i++) {
            cacheManager.get("key" + i);
            Thread.sleep(10);
        }
        cacheManager.put("key11", new Object());
        assertNull(cacheManager.get("key0"));
        assertNotNull(cacheManager.get("key11"));
    }

    public void testLFUCacheManager() {
        CacheManager cacheManager = CacheManager.getCacheManager("LFUCacheManager", CacheManager.LFU, 10);
        for (int i = 0; i < 10; i++) {
            cacheManager.put("key" + i, new Object());
        }
        for (int i = 0; i < 10; i++) {
            for (int j = 0; j < i; j++) {
                cacheManager.get("key" + i);
            }
        }
        cacheManager.put("key11", new Object());
        assertNull(cacheManager.get("key0"));
        assertNotNull(cacheManager.get("key11"));
    }
}

(Visited 114 times, 1 visits today)