Java 映射并发-修改异常

Java 映射并发-修改异常,java,collections,concurrency,Java,Collections,Concurrency,下面的代码由线程池执行。首先,映射不是并发的,所以我已经更改了它,但我仍然在第二行得到修改异常。 为了使这段代码成为线程安全的代码,我应该做哪些更改 ConcurrentHashMap<String, Account> entriesOnFile = IniReaderHelper.load(); for (Map.Entry<String,Account> entryFromFile: entriesOnFile.entrySet()) { EntryWrapp

下面的代码由线程池执行。首先,映射不是并发的,所以我已经更改了它,但我仍然在第二行得到修改异常。 为了使这段代码成为线程安全的代码,我应该做哪些更改

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;
    }               
}
堆栈跟踪指向第二行(“for”循环),并写入“EntryIterator.next”,这是否意味着我应该更改:

for (Map.Entry<String,Account> entryFromFile: entriesOnFile.entrySet())
for(Map.Entry entryFromFile:entriesOnFile.entrySet())

for(ConcurrentHashMap.entryFromFile:EntriesConfigure.entrySet())
这是对“账户”的减免

private static ConcurrentHashMap<String, Account> accounts = new ConcurrentHashMap<String, Account>();
私有静态ConcurrentHashMap帐户=新ConcurrentHashMap();

就我所见,跨线程共享帐户映射毫无意义(每次调用load()时都会清除和重建映射,因此最简单的修复方法是删除共享静态映射(帐户)并使load()生效)每次调用时创建并返回一个新映射。

根据您目前所说的,映射似乎是共享的。您可以同步对load方法的访问并复制映射的内容,然后再让另一个线程更改accounts字段。另一个选项是更改load方法以接受它可以填充的映射,而不是让它变异成共享的


话虽如此,异常还是没有意义的。CHM不会返回HashMap$EntryInterator,它会返回ConcurrentHashMap$EntryInterator,因此无法抛出您在此处描述的堆栈。我猜您不是在运行发布的代码,而是错误地运行了旧版本。请尝试在调试器中运行,或添加日志状态nt验证发布的代码是否实际运行。

看起来您并不是在修改EntriesConfigure映射,因此可能存在您没有向我们显示的代码,或者您没有告诉我们您的异常实际是什么。我没有尝试修改映射。我从文件中将Account类型的一些条目读取到EntriesConfigle中。然后我在e映射并将其名称与entryName进行比较,如果匹配,我会做一些事情。我得到的例外是修改,它位于第2行,其中“for”是的。我从我的一个客户那里得到了日志,但我无法在实验室中重新创建它,因为这部分代码都是在极端情况下运行的。你应该发布堆栈跟踪!听起来好像还有其他事情发生,因为如果你不修改映射,那么你就没有理由得到ConcurrentModificationXCeption。堆栈跟踪意味着您仍在使用HashMap,而不是ConcurrentHashMap。如果您参考条目集的api定义,“视图的迭代器是”弱一致的“迭代器不会抛出ConcurrentModificationException,并保证遍历迭代器构造时存在的元素,并且可能(但不保证)反映构造后的任何修改。。因此,如果您实际使用的是并发哈希映射,则在对映射进行迭代时不可能引发此异常。发布
帐户
的声明。堆栈跟踪表明它是
哈希映射
,而不是
并发哈希映射
,但“加载”的意图可能更像是“刷新”对于单例,在这种情况下,设计方面可能是OK的。此代码仅在出现问题时运行,我们需要重新构建映射,这就是为什么它是静态的,通常此代码不被读取。您可能希望在类中封装映射及其加载,并对重新加载应用并发控制,以确保线程不被读取您可以通过使用synchronized关键字或显式锁以及可能的时间戳来指示上次重新加载映射的时间。无法执行此操作,因为:for(map.Entry entryFromFile:entrienfile.entrySet())我不应该使用ConcurrentHashMap.Entry而不是Map.Entry吗?这个异常在我的实验室里没有发生,它发生在一个客户的身上,所以我不能真正测试任何东西。在我将Map移动到concurrent之前,我开始相信客户使用了错误的代码版本。这基本上就是我要说的……看看CHM代码,它无法生成ce当前的stacktrace->这不是正在运行的代码
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>();