【发布时间】:2013-06-12 16:26:36
【问题描述】:
以下代码由线程池执行。首先,地图不是并发的,所以我已经改变了它,但我仍然在第二行得到修改异常。 为了使这段代码成为线程安全的,我应该进行哪些更改?
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;
}
}
更多信息: 下面是返回地图的 .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>();
【问题讨论】:
-
您似乎没有在修改 entriesOnFile 映射,因此您没有向我们显示代码,或者您没有告诉我们您的异常实际上是什么。
-
我不想修改地图。我从一个文件中读取了一些 Account 类型的条目到 entryOnFile 中。然后我检查地图中的每个条目并将其名称与 entryName 进行比较,如果匹配,我会做一些事情。我得到的例外是修改,它在第二行,“for”在哪里。我从我的一位客户那里得到了日志,我实际上无法在实验室中重新创建它,因为这部分代码是在极端情况下运行的。
-
您应该发布堆栈跟踪!听起来好像还有其他事情发生,因为如果您不修改地图,那么您没有理由得到 ConcurrentModificationException。
-
您的堆栈跟踪表明您仍在使用 HashMap 而不是 ConcurrentHashMap。如果您参考条目集的 api 定义“视图的迭代器是一个“弱一致”迭代器,它永远不会抛出 ConcurrentModificationException,并保证遍历元素,因为它们在构造迭代器时存在,并且可能(但不保证)反映施工后的任何修改。”。因此,如果您实际上使用的是并发哈希映射,则在遍历映射时应该不可能抛出此异常。
-
发布
accounts的声明。堆栈跟踪表明它是HashMap,而不是ConcurrentHashMap
标签: java collections concurrency