This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.
It does not cause a severe problems, but is noticeable as a hot spot in self profiler - synchronized add|remove|fireListeners() with internal cloning of the lists before firing of the events. This can be re-implemented more easily and more performance-friendly using classes from Java 7 concurrent collections, for example: https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentLinkedDeque.html "Note: Iterators are weakly consistent, returning elements reflecting the state of the deque at some point at or since the creation of the iterator. They do not throw ConcurrentModificationException, and may proceed concurrently with other operations." More details @ https://docs.oracle.com/javase/8/docs/technotes/guides/collections/overview.html Examples: api.debugger\src\org\netbeans\api\debugger\Lookup.java - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - private final class MetaInfLookupList<T> extends LookupList<T> implements PositionedList<T>, Customizer { private List<PropertyChangeListener> propertyChangeListeners; @Override public synchronized void addPropertyChangeListener(PropertyChangeListener listener) { if (propertyChangeListeners == null) { propertyChangeListeners = new ArrayList<PropertyChangeListener>(); } propertyChangeListeners.add(listener); } @Override public synchronized void removePropertyChangeListener(PropertyChangeListener listener) { propertyChangeListeners.remove(listener); } private void firePropertyChange() { List<PropertyChangeListener> listeners; synchronized (this) { if (propertyChangeListeners == null) { return ; } listeners = new ArrayList<PropertyChangeListener>(propertyChangeListeners); } PropertyChangeEvent evt = new PropertyChangeEvent(this, "content", null, null); for (PropertyChangeListener l : listeners) { l.propertyChange(evt); } } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - private final class MetaInfLookupList<T> extends LookupList<T> implements PositionedList<T>, Customizer { private ConcurrentLinkedDeque<PropertyChangeListener> propertyChangeListeners = new ConcurrentLinkedDeque<>(); @Override public void addPropertyChangeListener(PropertyChangeListener listener) { propertyChangeListeners.add(listener); } @Override public void removePropertyChangeListener(PropertyChangeListener listener) { propertyChangeListeners.remove(listener); } private void firePropertyChange() { if (propertyChangeListeners.isEmpty()) { return ; } PropertyChangeEvent evt = new PropertyChangeEvent(this, "content", null, null); for (PropertyChangeListener l : propertyChangeListeners) { l.propertyChange(evt); } } Another similar use-case api.debugger\src\org\netbeans\api\debugger\DebuggerManager.java - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - public final class DebuggerManager implements ContextProvider { private Vector listeners = new Vector (); private final HashMap listenersMap = new HashMap (); private void firePropertyChange (String name, Object o, Object n) { initDebuggerManagerListeners (); Vector l = (Vector) listeners.clone (); Vector l1; synchronized (listenersMap) { l1 = (Vector) listenersMap.get (name); if (l1 != null) l1 = (Vector) l1.clone (); } int i, k = l.size (); for (i = 0; i < k; i++) { try { ((DebuggerManagerListener)l.elementAt (i)).propertyChange (ev); } catch (Exception ex) { Exceptions.printStackTrace(ex); } }