我有以下代码:
for (String helpId : helpTipFragCache.getKeys())
{
List<HelpTopicFrag> value = helpTipFragCache.getValue(helpId);
helpTipFrags.put(helpId, value);
}
helpTipFragCache 有一个机制来加载缓存,如果需要的值是空的。getKeys() 方法触发 this 并在调用 this 时加载缓存。但是在上述情况下,我看到了不同的行为。
我首先快速调试它以查看缓存是否确实在填充(在 Eclipse 中)。我走了过去,从未进入 for 循环(由于一个空的迭代器)。
然后我再次调试它(使用相同的代码)并进入 getKeys() 并在那里分析整个过程。然后它做了它应该做的一切,迭代器有值可以迭代,并且控制台中很平静。
我已通过更改代码来解决此问题:
Set<String> helpIds = helpTipFragCache.getKeys();
helpIds = helpTipFragCache.getKeys();
for (String helpId : helpIds)
{
List<HelpTopicFrag> value = helpTipFragCache.getValue(helpId);
helpTipFrags.put(helpId, value);
}
显然调试触发了一些初始化或行为不同的东西,有谁知道是什么原因造成的?基本上,从返回的集合创建迭代器会发生什么?
其他一些相关信息:
- 此代码在服务器启动时执行(tomcat)
- 从包含的 jar 执行时,此代码的行为与预期不同,但在同一代码库中时会如此
- 该集合是一个集合
编辑
附加代码:
public Set<String> getKeys() throws Exception
{
if (CACHE_TYPE.LOAD_ALL == cacheType)
{
//Fake a getValue call to make sure the cache is loaded
getValue("");
}
return Collections.unmodifiableSet(cache.keySet());
}
public final T getValue(String key, Object... singleValueArgs) throws Exception
{
T retVal = null;
if (notCaching())
{
if (cacheType == CACHE_TYPE.MODIFY_EXISTING_CACHE_AS_YOU_GO)
{
retVal = getSingleValue(key, null, singleValueArgs);
}
else
{
retVal = getSingleValue(key, singleValueArgs);
}
}
else
{
synchronized (cache)
{
if (needToLoadCache())
{
logger.debug("Need to load cache: " + getCacheName());
if (cacheType != CACHE_TYPE.MODIFY_EXISTING_CACHE_AS_YOU_GO)
{
Map<String, T> newCache = null;
if (cacheType != CACHE_TYPE.MODIFY_EXISTING_CACHE)
{
newCache = getNewCache();
}
else
{
newCache = cache;
}
loadCache(newCache);
cache = newCache;
}
lastUpdatedInMillis = System.currentTimeMillis();
forceLoadCache = false;
}
}
...//code in here does not execute for this example, simply gets a value that is already in the cache
}
return retVal;
}
回到原来的类(之前的代码是从哪里发布的):
@Override
protected void loadCache(
Map<String, List<HelpTopicFrag>> newCache)
throws Exception
{
Map<String, List<HelpTopicFrag>> _helpTipFrags = helpDAO.getHelpTopicFrags(getAppName(), _searchIds);
addDisplayModeToFrags(_helpTipFrags);
newCache.putAll(_helpTipFrags);
}
上面,进行了数据库调用以获取要放入缓存的值。