【发布时间】:2014-06-19 02:14:42
【问题描述】:
使用此代码:
public class SynchroApp {
public static void main(String[] args) {
final List<String> unsyList = new ArrayList<>();
final List<String> syList = Collections.synchronizedList(unsyList);
TimerTask changeList = new TimerTask() {
boolean addElem = false;
@Override
public void run() {
// add / remove elements to keep size between 2 and 9
if (syList.size() < 2)
addElem = true;
else if (syList.size() > 8)
addElem = false;
if (addElem)
syList.add(String.valueOf(System.currentTimeMillis()));
else
syList.remove(0);
}
};
TimerTask reverseList = new TimerTask() {
@Override
public void run() {
try {
for (String s : syList)
s = new StringBuffer(s).reverse().toString();
} catch (Exception e) {
System.out.println("Exception: " + e);
}
}
};
new Timer().scheduleAtFixedRate(changeList, 0L, 30L);
new Timer().scheduleAtFixedRate(reverseList, 0L, 20L);
}
}
为什么我仍然在Iterator.next 上收到一些ConcurrentModificationException?
编辑:reverseList 中列表元素的更新不起作用(如 cmets 中所述)。此代码应按预期工作:
for (int i = 0; i < syList.size(); i++)
syList.set(i, new StringBuffer(syList.get(i)).reverse().toString());
【问题讨论】:
-
我在您发布的代码中没有看到
next调用。但是请注意,reverseList的run中的循环目前没有做任何事情(Java 字符串是不可变的)。 -
您不能在使用迭代器的同时修改列表的内容。迭代器将意识到对列表进行了更改并抛出此异常。
-
@kviiri 即使类是可变的,它也不会做任何事情,因为它使用了一个临时变量。
-
next 隐含在 (String s : syList) 中。我认为 s 是用 reverse() 的结果更新的,但这只是一个例子。
-
@Approachingminimums,是的,
s是对列表元素的引用,但您没有更改列表的元素,而是更改(本地)引用以完全引用完全不同的字符串.由于字符串是不可变的,因此您需要删除旧字符串并添加一个新字符串来实际替换某些内容。如果字符串是可变的,您可以执行s.replace(...)之类的操作,但s = "something"仍然行不通。
标签: java arraylist iterator concurrentmodification