我是java的新手,所以如果我说的话听起来很新鲜,请提前对不起,请保持温和。
我已经实现了一个基本的观察者模式。一些观察者应该只听一个更新,然后立即从观察者/听众列表中删除自己。但是,每当我尝试这样做时,我都会遇到着名的 java.util.concurrentmodificationexception 错误。
我显然遇到了这个错误,因为我在更改列表的同时还在迭代它,但我仍然不确定什么是正确的解决方案。我想知道我是否以正确的方式做到这一点。如果我是,那么它需要什么样的解决方案才能使它工作?如果我不是,我想得到更好的方法来实现我想要做的建议。
这是我的代码:
public interface Listener {
public void onValueChange(double newValue);
}
public class Observed {
private int value;
List<Listener> listeners = new ArrayList<>();
public void addListener(Listener toAdd) {
listeners.add(toAdd);
}
public void removeListener(Listener toRemove) {
listeners.remove(toRemove);
}
public void changeValue(double newValue) {
value = newValue;
for (Listener l : listeners) l.onValueChange(newValue);
}
}
public class SomeClassA implements Listener{
private Observed observed;
SomeClassA(Observed observed) {
this.observed = observed;
}
@Override
public void onValueChange(double newValue) {
System.out.println(newValue);
observed.removeListener(this);
}
}
public class SomeClassB implements Listener{
@Override
public void onValueChange(double newValue) {
System.out.println(newValue);
}
}
public class ObserverTest {
public static void main(String[] args) {
Observed observed = new Observed();
SomeClassA objectA = new SomeClassA(observed);
SomeClassB objectB = new SomeClassB();
observed.addListener(objectB);
observed.addListener(objectA);
observed.changeValue(4);
}
}
答案 0 :(得分:6)
一种方法是去CopyOnWriteArraylist而不是ArrayList。
CopyOnWriteArraylist是ArrayList的线程安全变体,其中 所有的变异操作(添加,设置等)都由实现 制作基础数组的新副本。
在您的案例中抛出的原因
在方法changeValue()
下迭代集合时,您正在直接修改集合答案 1 :(得分:1)
在迭代集合时,无法从集合中删除项目。也就是说,除非您使用Iterator#remove方法。由于在这种情况下不可能,所以另一种方法是制作一个监听器列表的副本并对其进行迭代。在这种情况下,原始侦听器列表可以由各个侦听器自由操作:
public void changeValue(double newValue) {
value = newValue;
List<Listener> copyOfListeners = new ArrayList<Listener>(listeners);
for(Listener l : copyOfListeners) {
l.onValueChange(newValue);
}
}
答案 2 :(得分:0)
下面的代码有效,所以你可以尝试它做的任何事情。
import java.util.Observable;
import java.util.Observer;
class Model extends Observable {
public void setX(double x) {
this.x=x;
System.out.println("setting x to "+x);
setChanged();
notifyObservers();
}
double x;
}
class A implements Observer {
A(Model model) {
this.model=model;
}
@Override public void update(Observable arg0,Object arg1) {
System.out.println(getClass().getName()+" "+((Model)arg0).x);
((Model)arg0).deleteObserver(this);
}
Model model;
}
class B implements Observer {
@Override public void update(Observable arg0,Object arg1) {
System.out.println(getClass().getName()+" "+((Model)arg0).x);
}
}
public class So19197579 {
public static void main(String[] arguments) {
Model model=new Model();
model.addObserver(new A(model));
model.addObserver(new B());
model.setX(4);
model.setX(8);
}
}