【问题标题】:Java modifying list concurrently at different placesJava同时在不同的地方修改列表
【发布时间】:2016-04-10 00:31:00
【问题描述】:

我有这段代码,我在其中使用迭代器遍历 ArrayList,例如:

Iterator iterator = list.iterator();
while (iterator.hasNext()) {
  Element element = iterator.next();
  iterator.remove();
  handle(element)
}

其中“句柄(元素元素)”如下所示:

ListIterator iterator = list.listiterator();
iterator.add(element);

现在这给出了一个 ConcurrentModificationException,因为第一个方法中的 iterator 没有使用新添加的元素进行更新。

我目前已经使用CopyOnWriteArrayList 解决了这个问题,但是这些对于性能来说非常昂贵。有没有更好的方法来解决这个问题?

提前致谢!

(注意:这个例子没有任何意义,只是为了说明我所面临的问题)


我将尝试解释我为什么这样做:

  • 我的主类中有一个需要执行的“命令”列表

  • 我有一个 while 循环(示例中的代码 1),它遍历这些命令并一个接一个地执行它们,同时在从列表中执行时将它们删除。

  • 在执行命令时,该命令可以依次将新命令添加到保存在我的主类中的列表中。 (这实际上有点复杂:处理命令会要求客户端做出响应,而客户端又会用命令响应,并且该命令将被添加到保存的列表中)。

【问题讨论】:

  • 你为什么要这样做?也就是说,您为什么要尝试使用两种不同类型的迭代器来处理同一个列表?
  • 你能试着解释一下你的真实例子,还是它的简化版本?
  • 我已经尽力解释我想要做的最好的事情(见编辑)。很抱歉造成混乱,感谢您的考虑!
  • 您不应该在迭代该列表的循环中修改列表。您可以首先将其作为数组获取,然后通过数组的元素从列表中删除,而不是直接通过迭代器中的列表本身。在迭代列表时,您不能通过删除元素来影响列表。
  • 这个列表有多大?如果只是几个项目,那么不要太担心性能。担心你是否可以真正衡量一个问题。如果大量时间花在其他操作(例如与客户沟通)上,副本也不太可能成为问题。

标签: java iterator concurrentmodification copyonwritearraylist


【解决方案1】:

鉴于上述要求,简单的解决方案是使用Queue (javadoc) 而不是List

我的主类中有一个需要执行的“命令”列表

Queue 可以表示一系列命令。

我有一个 while 循环(示例中的代码 1),它遍历这些命令并一个接一个地执行它们,同时在从列表中执行时将它们删除。

Queue 的等价物是重复调用remove()poll() 等来获取并删除Queue 中的第一个命令。您反复执行此操作,直到 Queue 为空。

请注意,这不涉及Iterator

在执行命令时,该命令可以依次将新命令添加到保存在我的主类中的列表中。

这可以通过调用add()offer()Queue 添加命令来完成。


请注意,Queue 的许多不同实现具有不同的属性:

  • 具有有限或无限大小的队列
  • 阻塞或不阻塞的队列
  • 简单的 FIFO 队列与 LIFO 队列或优先级队列

【讨论】:

  • 我不知道您可以在使用 poll() 时安全地遍历队列。这确实正是我想要的。谢谢!对于那些想知道的人:我已经将我的队列实现为 PriorityBlockingQueue ,因为我的命令在不同的线程中执行并且可以同时修改队列(因此​​ PriorityQueue 是不够的)。
猜你喜欢
  • 2018-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-28
  • 1970-01-01
  • 2022-07-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多