В настоящее время у меня реализован HashMap, который
private static Map<String, Item> cached = new HashMap<String, Item>();
а Item — это объект со свойствами Date expireTime и 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. Если данные возвращаются нулевыми, то мы создаем и данные и кэшируем их в 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
может быть очень полезным. - person toto2   schedule 07.07.2011