我已经阅读了一些关于列表并发性的内容,并且我正面临这个问题:
我有一份我需要经历的清单。每次我处理此列表中的元素时,都会发生一些列表更改效果(在许多其他事情中)。
这些列表更改效果不会在循环期间直接发生。它们可以通过对其中一个元素的动作触发。所有这些都是同步完成的。
这是目前的简化版本。
class Container {
List<Element> elements;
// It starts here
public void process() {
for (Element el: this.elements)) {
el.doSomething(this);
}
}
public void removeElement(Element el) {
this.elements.remove(el);
}
}
class Element {
public void doSomething(Container c) {
this.doThis();
this.getAction().applyTo(c);
}
}
class MyAction implements Action<Container> {
void applyTo(Container c) {
for (Element el: this.getElements())) { // getElements does an immutable copy of this.elements
el.doThat();
if(el.shouldBeRemoved()) {
c.removeElement(el);
}
}
}
}
我找到的最佳解决方案如下:
public void process() {
for (Element el: this.getElements()) {// getElements does an immutable copy of this.elements
if (!this.elements.contains(el)) continue;
el.doSomething(this);
}
}
它没有说明一个元素可以添加到列表中的事实,但我目前不需要处理在process()
调用期间添加的元素。
所以这样可行,但会导致很多列表复制。
我已经考虑过CopyOnWriteArrayList
,但它仍然会复制列表,除非它可能会在循环过程中复制很多时间,但性能较差。
我已将ListIterator
放在一边,因为我需要引用原始列表迭代器。
我想到的最后一个选项是标记元素而不是用null替换它们,这样它们就会被任何动作忽略,但这会迫使我添加很多条件,如:el.isFlagOk()
。另外,它会强制我复制元素,以防需要将删除的元素添加回到最后(而不是像我现在那样重置它)。
仅供参考,该列表的最大功能大小为10。
是否存在支持这种交织行为的列表类型结构?
答案 0 :(得分:0)
那么你需要的是元素可以在迭代列表时潜在地调整列表吗?
对于这个可能你可以看看容器中有2个列表。其中一个可以被迭代获得,一个被编辑。编辑后需要在迭代完成时替换迭代列表。
所以:
class Container {
List<Element> elements;
List<Element> itr;
...
public void process() {
for (Element el: itr) {
el.doSomething(this);
}
swap();
}
private void swap(){
itr = elements;
elements = getElements();//assuming getElements does an immutable copy of this.itr
}
}