以下代码由线程池执行。首先,Map不是并发的,所以我改变了,但我仍然在第二行得到修改异常。 我应该做些什么改变才能将这段代码变成线程安全的?
ConcurrentHashMap<String, Account> entriesOnFile = IniReaderHelper.load();
for (Map.Entry<String,Account> entryFromFile: entriesOnFile.entrySet())
{
EntryWrapper wrapperFromEntriesFile = new EntryWrapper(entryFromFile.getValue());
if (wrapperFromEntriesFile.getName().equals(entryName))
{
Tracer.info("Found matching entry from the entries file for +'" + entryName + "'");
synchronized(this)
{
context.put(RequestServices.ENTRY_WRAPPER, wrapperFromEntriesFile);
}
entry = wrapperFromEntriesFile;
break;
}
}
更多信息: 下面是返回map的.load()函数的代码:
static public ConcurrentHashMap<String, Account> load() throws Exception
{
BufferedReader reader = null;
accounts.clear();
try
{
reader = new BufferedReader(new FileReader(getEntriesFile()));
Account current = null;
String accountName;
String line;
while ((line = reader.readLine()) != null)
{
... do stuff here then adding entry to the amp
accounts.put(accountName, current);
}
}
finally
{
if (reader != null)
reader.close();
}
return accounts;
}
这是堆栈跟踪:
error code [1] : java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(Unknown Source)
at java.util.HashMap$EntryIterator.next(Unknown Source)
at java.util.HashMap$EntryIterator.next(Unknown Source)
at .....call(AsyncCommand.java:78)
堆栈跟踪指向第二行('for'循环)并写入“EntryIterator.next”所以这不意味着我应该更改:
for (Map.Entry<String,Account> entryFromFile: entriesOnFile.entrySet())
到
for (ConcurrentHashMap.Entry<String,Account> entryFromFile: entriesOnFile.entrySet())
以下是“帐户”的删除
private static ConcurrentHashMap<String, Account> accounts = new ConcurrentHashMap<String, Account>();
答案 0 :(得分:0)
据我所知,跨线程共享帐户映射是没有意义的(您在每次调用load()时都清除并重建映射,因此最直接的解决方法是删除共享静态映射(帐户)并让load()在每次调用时创建并返回一个新Map。
答案 1 :(得分:0)
在我看来,到目前为止,我认为地图是完全共享的。您可以同步访问加载方法并复制地图的内容,然后让另一个线程改变帐户字段。另一种选择是更改加载方法以接受它可以填充的地图,而不是让它改变共享地图。
话虽如此,这个例外没有意义。 CHM不返回HashMap $ EntryIterator,它返回一个ConcurrentHashMap $ EntryIterator,并且没有办法抛出你在这里描述的堆栈。我的猜测是你没有运行你发布的代码但是错误地运行了旧版本。尝试在调试器中运行,或添加日志语句以验证实际运行的已发布代码。