2011-01-30 103 views
1

早上好,希望得到一些可能比我自己更了解Java的人的帮助。我来自.NET背景,并且负责跟踪供应商提供的解决方案中的问题。我相信我已经找到了它,但如果可能的话,我想要第二,第三或第四个意见。迭代器和嵌套哈希表的Java并发问题

我认为正在发生的是行号108(在下面的代码块中指出)正在修改声明为while循环外部的Iterator(memIter)。他们通过更改在循环中声明的实例来修改它,而不是原始对象,我相信它会抛出,因为在修改后的集合/ hastbale的第二次迭代上调用了“next”。我发现这个网站上的一些线程指向这个(http://stackoverflow.com/questions/602636/concurrentmodificationexception-and-a-hashmap),但因为它修改了一个集合(对不起,如果这些是.NET的条款)在一个集合中(从迭代器中的一个项目的属性hastable中移除一个成员),我会假设同样的逻辑会适用,但它不是我的空间。另外如果我的假设是正确的可以somone请提供正确的实施?

STACK

java.util.ConcurrentModificationException 堆栈跟踪: java.util.ConcurrentModificationException 在java.util.HashMap中$ HashIterator.nextEntry(HashMap.java:793) 在$的java.util.HashMap ValueIterator.next(HashMap.java:822) at xxx.xxxxx.xx.xxxxxxx.end(RoleOrganizer.java:108) at(xxxxxxxxx.java:568) at xxx.xxxx.xxxxxxx.handleRequest(xxxxHandler.java :74) at com.xxxxx.server.JavaInstanceMethod.execute(JavaInstanceMethod.java:33) at xx.xxxxx xx.execute(AppServer.java:1469) at xxx.xx.executeRequest(xxxxxjava:1269) at xxx.xxxxx.server.xxxx.doGet(xxxxx.java:350) at javax.servlet.http.HttpServlet。服务(HttpServlet.java:690) at javax.servlet.http.HttpServlet.service(HttpServlet.java:803) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) at org。 apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) at org.apache.catalina.core.StandardContextValve.invoke( StandardContextValve.java:175) at org.apache.catalina.core.StandardHostValve.invoke(Standar org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org。 apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286) at org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:190) at org.apache.jk.common.HandlerRequest.invoke( HandlerRequest.java:283) 在org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:767) 在org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:697) 的组织。 apache.jk.common.ChannelSocket $ SocketConnection.runIt(ChannelSocket.java:889) at org.apache.tomcat.util.thread s.ThreadPool $ ControlRunnable.run(ThreadPool.java:690) at java.lang.Thread.run(Thread。的java:619)

用所示堆栈错误行数108

线87 anpublic空隙端()

{

Iterator iter = new ArrayList(this.m_member.getRoles()).iterator(); 

while (iter.hasNext()) 

{ 

    UserType rt = (UserType)iter.next(); 
    if (!this.m_roleMap.containsKey(rt.getGID())) 
    { 
    this.m_member.removeRole(ut); 
    } 
} 
iter = this.m_roleMap.values().iterator(); 

线99
而下面的代码(iter.hasNext ())

{ 
    UserType ut = (UserType)iter.next(); 
    if (ut.isUnique()) 
    { 
    Iterator memIter = this.m_member.doTask().lookUpMembers().iterator(); 
    while (memIter.hasNext()) 
    { 

第108行
StoreMember mem =(StoreMember)memIter.next();

 if (mem.doWork() != this.m_member.getId()) 
     { 
     if ((mem.hasRole(ut)) && (!mem.isFormer())) 
     { 
      mem.removeRole(ut); 
     } 
     } 
    } 
    } 

回答

1

什么,我认为正在发生的是,行号108(在下面的代码块所示)被修改迭代器

我怀疑你误解了下你得到哪些情况ConcurrentModificationException

A ConcurrentModificationException不是由于并发修改迭代器,而是由于基础集合的并发修改。

从文档:

此异常可能由已检测出的对象的并发修改时这种修改是不允许的方法被抛出。

例如,通常不允许一个线程修改集合,而另一个线程正在迭代它

0

这当然听起来就像是当你迭代它改变了集合的问题,虽然它的棘手跟随到底发生了什么的,没有看到doTasklookUpMembers。 (请注意,同样的逻辑也适用于.NET。)

两个可能的解决方法(只适用于一个!):

  • 复制lookUpMembers无论是内lookUpMembers本身或在您使用它的结果。从中创建一个新列表,然后从原始集合中删除项目并不重要。
  • 创建一个要在循环中删除的角色列表,然后再次分别循环删除它们。

就我个人而言,我可能会选择第一个,因为这意味着您应该只需要进行一次更改。调用doTask().lookUpMembers()的结果不是声音就像它直接支持原始集合。无论哪种方式,你应该清楚地记录你在做什么。

+0

非常感谢您的回复。主要任务是验证它是问题的根源,我认为你已经帮助我得出结论...再次感谢 – 2011-01-30 08:27:45

1

在迭代它时,您无法修改集合。解决方案是使用Iterator对象,并直接调用remove。

使用ConcurrentHashMap有所帮助,因为它不会引发ConcurrentModificationException。从一个ConcurrentHashMap:

检索操作(包括get) 一般不阻塞,因此,可能会重叠 与更新操作(包括投资 和删除)。检索反映了最近完成的 更新操作的 结果,该更新操作持有它们的 开始。对于聚合操作 put all and clear,并发 检索可能反映了插入或仅删除了一些条目 。 类似地,迭代器和枚举 返回自从创建迭代器/枚举以来反映哈希表的状态 处的某个点处的元素或者 。他们不会 抛出ConcurrentModificationException。 但是,迭代器被设计为 一次只能由一个线程使用。

+0

在迭代器上调用remove可能不合适 - removeRole可能有其他副作用。 – 2011-01-30 08:13:51

+0

@Jon:你花了多少时间在SO上? :)...我回答的每第三个问题,还有你的评论或答案。对SO有特别的兴趣,或者只是狂热? :)我无法做我的日常工作,并在这里度过这么多时间。 – Daniel 2011-01-30 08:37:10