HashMap损坏/性能问题

时间:2011-07-07 15:54:47

标签: java performance hashmap concurrenthashmap

目前我已经实现了HashMap

private static Map<String, Item> cached = new HashMap<String, Item>();

和Item是具有属性的对象 Date expirationTime和byte [] data

当多个线程同时开始执行此操作时,将使用此映射。 我做的检查是

1

public static final byte[] getCachedData(HttpServletRequest request) throws ServletException
{
    String url = getFullURL(request);
    Map<String, Item> cache = getCache(request);  // this chec
    Item item = null;

    synchronized (cache)
    {
        item = cache.get(url);
        if (null == item)
            return null;

        // Make sure that it is not over an hour old.
        if (item.expirationTime.getTime() < System.currentTimeMillis())
        {
            cache.remove(url);
            item = null;
        }
    }

    if (null == item)
    {
        log.info("Expiring Item: " + url);
        return null;
    }

    return item.data;
}

2。如果数据返回null,那么我们创建并数据并将其缓存在hashMap

public static void cacheDataX(HttpServletRequest request, byte[] data, Integer minutes) throws ServletException
{
    Item item = new Item(data);
    String url = getFullURL(request);
    Map<String, Item> cache = getCache(request);

    log.info("Caching Item: " + url + " - Bytes: " + data.length);
    synchronized (cache)
    {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.MINUTE, minutes);
        item.expirationTime = cal.getTime();
        cache.put(url, item);
    }
}

似乎多个线程访问say密钥(在这种情况下是url),然后数据在同一个密钥位置被多次添加到缓存[因为getCacheData将为多个线程返回null,因为hashmap尚未完成第一次写入数据线程]

有关如何解决问题的任何建议吗?

2 个答案:

答案 0 :(得分:2)

在cacheDataX中,在添加之前(在synchronized块内)添加对项目存在的检查。

synchronized (cache)
    {
        if (cache.get(url) == null) {
            Calendar cal = Calendar.getInstance();
            cal.add(Calendar.MINUTE, minutes);
            item.expirationTime = cal.getTime();
            cache.put(url, item);
        }
    }

这将确保已经完成查找并返回null的多个线程无法将所有相同的数据添加到缓存中。一个人将添加它,其他线程将默默忽略,因为缓存已经更新。

答案 1 :(得分:1)

您需要一个同步块,以涵盖从缓存中获取内容以及插入缓存中的内容。代码就在于你有一个竞争条件:多个线程可以在任何人执行第2步之前执行第1步。