Java 删除同步方法中的ArrayList元素
我有一个Java 删除同步方法中的ArrayList元素,java,synchronization,Java,Synchronization,我有一个synchronized方法,它在ArrayList上运行,然后通过调用ArrayList.clear()删除其元素 为什么当多个线程调用此方法时,即使它是同步的,我也会得到ConcurrentModificationException 关键字synchronized不是用来避免此类错误的吗 public MyOuterClass { private class MyInnerClass implements MyCallback { private class MyIn
synchronized
方法,它在ArrayList
上运行,然后通过调用ArrayList.clear()
删除其元素
为什么当多个线程调用此方法时,即使它是同步的,我也会得到ConcurrentModificationException
关键字synchronized
不是用来避免此类错误的吗
public MyOuterClass {
private class MyInnerClass implements MyCallback {
private class MyInnermostClass implements Runnable {
@Override
public void run() {
if (condition) {
myMethod();
}
else {
synchronized (myArrayList) {
myArrayList.add(new MyObject());
}
}
}
public void myCallback() {
Thread myThread = new Thread(new MyInnermostClass());
myThread.start();
}
}
private ArrayList<MyObject> myArrayList;
public MyClass() {
myArrayList = new ArrayList<>();
}
private synchronized void myMethod() {
for (MyObject o: myArrayList) {
System.out.println(o);
}
myArrayList.clear();
}
}
如果您的方法是从多个线程调用的,那么它肯定需要同步。然而,听起来好像有别的事情在发生 尽管名称不同,
ConcurrentModificationException
与线程并发性(本质上)无关。相反,当迭代器注意到它所迭代的集合以某种意外的方式发生了更改时,就会抛出它。例如,即使使用单线程应用程序,以下操作也会生成一个ConcurrentModificationException
:
for (Object o : myArrayList) {
if (shouldRemove(o)) {
myArrayList.remove(o);
}
}
处理这种情况的正确方法是使用显式迭代器并使用它删除元素:
for (Iterator<Object> iter = myArrayList.iterator(), Object o;
iter.hasNext();
o = iter.next())
{
if (shouldRemove(o)) {
iter.remove();
}
}
这样,修改myArrayList的所有代码都会在list对象本身上同步。这就是所有代码吗?或者您是否在for循环中执行其他操作,如添加/删除/修改元素?请发布堆栈跟踪和实际代码。通常
ConcurrentModificationException
与线程无关(尽管多线程可能会加剧问题)。它来自于在迭代器仍在积极迭代列表时修改列表。您发布的代码不会生成该异常;正在进行其他操作(可能与已同步
)无关。同意,该代码不会导致出现所述异常。必须有一个代码,您可以在其中修改列表,由于异常与concurrentModificationCheck相关,因此您要么修改最终列表,要么如果不是最终列表,则必须使用迭代器在同步块时修改值,代码将正常工作。一定要让我们知道问题、完整堆栈跟踪或您没有放在这里的部分代码。@Tirafesi-我更新了我的答案,因为我有了更多信息。啊,我明白了。谢谢:D
for (Iterator<Object> iter = myArrayList.iterator(), Object o;
iter.hasNext();
o = iter.next())
{
if (shouldRemove(o)) {
iter.remove();
}
}
private void myMethod() {
synchronized (myArrayList) {
for (MyObject o: myArrayList) {
System.out.println(o);
}
myArrayList.clear();
}
}