【发布时间】:2011-07-07 15:54:47
【问题描述】:
目前我已经实现了 HashMap
private static Map<String, Item> cached = new HashMap<String, Item>();
并且 Item 是一个具有属性的对象 Date expireTime 和 byte[] 数据
当多个线程同时开始命中此映射时使用此映射。 我做的检查是
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尚未完成首先写入数据线程]
关于如何解决问题的任何建议?
【问题讨论】:
-
看
java.util.concurrent.ConcurrentHashMap;putIfAbsent方法可能非常有用。 -
日历是一个很重的物体。如果您查看 GregorianCalender 的来源,您就会明白为什么。尝试改用 System.currentTimeMillis()。
标签: java performance hashmap concurrenthashmap