我正在研究一些我正在使用Observer设计模式的项目。 主题类是:
public class Subject {
private List<Observer> observers = new ArrayList<Observer>();
private int state;
public void setState(int state) {
this.state = state;
notifyAllObservers();
}
public void attach(Observer observer){
observers.add(observer);
}
public void notifyAllObservers(){
for (Observer observer : observers) {
observer.update();
}
}
public void deattach(Observer observer) {
observers.remove(observer);
}
}
观察者界面是:
public abstract class Observer implements Runnable{
protected Subject subject;
public abstract void update();
public abstract void process();
}
名为HexObserver的Observer之一是:
public class HexaObserver extends Observer {
private ExecutorService threadpool = Executors.newFixedThreadPool(10);
public HexaObserver(Subject subject) {
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println("Hex String: "
+ Integer.toHexString(subject.getState()));
Future future = threadpool.submit(new HexaObserver(subject));
}
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("In run :D :D :D");
}
@Override
public void process() {
// TODO
}
}
测试它的类是:
public class Demo {
public static void main(String[] args) {
Subject subject = new Subject();
HexaObserver hob = new HexaObserver(subject);
System.out.println("First state change: 15");
subject.setState(15);
}
}
当我尝试运行此操作时,会出现一些错误:
First state change: 15
Hex String: f
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
at java.util.ArrayList$Itr.next(ArrayList.java:831)
at Observer.Subject.notifyAllObservers(Subject.java:23)
at Observer.Subject.setState(Subject.java:15)
at Observer.Demo.main(Demo.java:12)
In run :D :D :D
当我们尝试在不允许的情况下同时修改某些Object时,我没有理解为什么我收到此错误,因为ConcurrentModificationException
被抛出。
我错过了什么吗?
答案 0 :(得分:0)
同时发生了两件事:你正在迭代observers
并向observers
添加一个元素。这会导致您ConcurrentModificationException
一般来说,你可以做两件事:
observers
与synchronized
阻止的所有访问权限同步:
public void attach(Observer observer){
synchronized(observers){
observers.add(observer);
}
}
public void notifyAllObservers(){
synchronized(observers){
for (Observer observer : observers) {
observer.update();
}
}
}
public void deattach(Observer observer) {
synchronized(observers){
observers.remove(observer);
}
}
synchronized
,但随后它们将在Subject
的实例上进行同步,而不是在集合实例上进行同步。但是,在您的情况下,问题与update()
的问题有关
您确定HexaObserver
的{{1}}应该创建新的update
吗?因为您要将同一类的新实例添加到已包含该实例的集合中。
答案 1 :(得分:0)
ConcurrentModificationException
通常是您在Iterator
上使用Collection
的标志,并且在迭代时,您还修改了基础Collection
(请记住,foreach-expression是实际上是使用Iterator
)的快捷方式。解决这个问题的唯一方法是迭代原始集合的副本。如果您处于多线程环境中,还需要确保以线程安全的方式完成集合的副本。
所以你可以举例:
public class Subject {
private List<Observer> observers = new Vector<Observer>();
private int state;
public void setState(int state) {
this.state = state;
notifyAllObservers();
}
public void attach(Observer observer){
observers.add(observer);
}
public void notifyAllObservers(){
for (Observer observer : ((List<Observer)observers.clone())) {
observer.update();
}
}
public void deattach(Observer observer) {
observers.remove(observer);
}
}