我使用实现的PropertyChangeSupport类Flight,如下所示:
protected List changeListeners;
public void addPropertyChangeListener(PropertyChangeListener listenerToAdd){...}
public void removePropertyChangeListener(PropertyChangeListener listenerToRemove){...}
private void notifyChangeListeners(String message){...}
......经典的观察者模式。我想要完成的是创建新的Flight对象,但保留现有的PropertyChangeListeners。看起来简单的任务让我深入研究了多线程和并发问题,发现了“失效的倾听者问题”。
这是我的第一个“简单解决方案”,它不起作用:
public Flight newFlightWithOldListeners(List<Scans> scansList){
Flight newFlight=new FlightImpl();
newFlight.setScansList(scansList);
newFlight.setExplorerManager(this.getExplorerManager());
for (Iterator<PropertyChangeListener> iterator = this.getChangeListeners().iterator(); iterator.hasNext();) {
PropertyChangeListener listener=iterator.next();
newFlight.addPropertyChangeListener(listener);
iterator.remove();
}
return newFlight;
}
我没有收到任何错误,但这并不是应该的。所有PropertyChangeListeneres都保持链接到旧的Flight对象,并且在触发PropertyChangeEvents之前会触发它。
我完全错过逻辑吗?这看起来应该是微不足道的?
问题是关于设计。这是使用旧PropertyChangeListeners创建新对象的好设计吗?
答案 0 :(得分:6)
您在迭代时不能直接更改基础集合,否则您将获得ConcurrentModificationException
。您应该使用迭代器的remove()
方法。
而不是
this.changeListeners.remove(iterator.next());
只是做
iterator.remove()
至于你应该做的逻辑
for (Iterator<PropertyChangeListener> iterator = this.getChangeListeners().iterator(); iterator.hasNext();) {
PropertyChangeListener propertyChangeListener = (PropertyChangeListener )iterator.next();
newFlight.addPropertyChangeListener(propertyChangeListener);
iterator.remove();
}
答案 1 :(得分:0)
我怀疑您因iterator
而遇到问题,因为您在创建changeListers
后修改(删除元素)iterator
。在大多数情况下,iterator
不允许我们从外部更改list
。使用iterator.remove()
这将解决。