Похожие страницы: Java имеет структуру данных "LinkedConcurrentHashMap"?
Я ищу класс набора для содержания ссылок на слушателей события.
Идеально я хотел бы, чтобы набор имел следующие свойства (в порядке приоритета):
HashSet
чей итератор может возвратить элементы в неправильном порядке.WeakReference
s так, чтобы список слушателя не препятствовал тому, чтобы слушатели были собраны "мусор".Set
, таким образом, дубликаты автоматически удалены.Iterator
ориентированный на многопотоковое исполнение снимок набора, незатронутого добавлением новых слушателей. Также позволяет событиям быть поставленными на нескольких потоках. (Это не важно - я мог выполнить итерации по клону набора вместо этого.)Я знаю о некоторых классах, которые удовлетворяют некоторых, но не все эти критерии. Примеры:
java.util.LinkedHashSet
(#1 и № 3)java.util.WeakHashMap
, перенесенный Collections.newSetFromMap
(#2 и № 3)javax.swing.event.EventListenerList
(потребности некоторая дополнительная синхронизация) (#1 и № 4)java.util.concurrent.CopyOnWriteArraySet
(#1, № 3 и № 4)Но ничто и с № 1 и с № 2. Классу нравится, это существует в библиотеке где-нибудь?
Можно использовать WeakListeners (см. http://bits.netbeans.org/dev/javadoc/org-openide-util/org/openide/util/WeakListeners.html) и CopyOnWriteArraySet.
remove(ListenerType listener)
в источнике событий. В вашем методе register(SomeListener listener)
добавьте вместо него WeakListener в коллекцию:
listenerCollection.put((ListenerType)WeakListeners.create ((Типы слушателей)
.
ListenerType.class, listener, this));
Когда реальный слушатель будет удален из памяти, слабый слушатель будет уведомлен, и он сам удалит регистрацию. (Поэтому для регистрации ему нужна ссылка на источник (this
)). Регистрация выполняется с помощью рефлексии путем вызова метода delete из источника.
Вы можете обернуть каждую ссылку слушателя в слабовение , а затем используйте pophonwritearRayset .
Что касается ответа на вопрос, почему нужно делать принудительные покушения. Я видел случаи, когда кто-то использовал сообщение о совершении преступления, которое было неправильным или неясным. Приятно, если вы можете выполнить принудительную фиксацию, где вы можете исправить эту ошибку. Таким образом, обновленное сообщение о фиксации поступает в репозиторий, поэтому оно не теряется.
-121--990966- Единственные случаи (я могу подумать), когда вам нужно установить предметы на null
, это несколько случаев, когда участвует DOM.
Например, если имеется узел с несколькими дочерними узлами, каждый из которых имеет обработчик onclick, определенный анонимными функциями, то установка для каждого щелчка значения null
будет хорошей идеей (чтобы избежать непреднамеренных циклических ссылок).
<div id="delete_me">
<span></span>
<span></span>
</div>
var theDiv = document.getElementById('delete_me');
for (var i=0; i < theDiv.childNodes.length; i++) {
theDiv.childNodes[i].onclick = function () {
// stuff
};
}
// Later...
// Delete stuff.
var divToDelete = document.getElementById('delete_me');
// Remove all the onclicks
for (var i=0; i < theDiv.childNodes.length; i++) {
theDiv.childNodes[i].onclick = null;
}
// Delete the div
divToDelete.parentNode.removeChild(divToDelete);
-121--5044747- Я собираюсь начать с того, что у вас есть пара требований, которые не имеют смысла вместе. Вы ищете коллекцию, которая удаляет дубликаты и поддерживает слабые ссылки, что указывает мне на то, что слушатели могут появляться и исчезать в неопределенное время. Тем не менее, необходимо сохранить порядок вставки и разрешить одному слушателю отменять все последующие уведомления. Для меня это звучит как рецепт труднодоступных ошибок, и я настоятельно предлагаю переосмыслить его.
Это означает, что у вас есть одно требование, которое в значительной степени управляет решением: вы не хотите, чтобы ConcurrentModifityException
, которое могло бы исходить от обычного итератора. Это значит, что вам придется скопировать исходный список. По пути вы можете проверить и удалить пустые ссылки:
// the master list
List<WeakReference<MyListener>> _list = new ArrayList<WeakReference<MyListener>>();
// inside your send-notification method
List<MyListener> toNotify = new ArrayList<MyListener>(_list.size());
Iterator<WeakReference<MyListener>> itx = _list.iterator();
while (itx.hasNext())
{
WeakReference<MyListener> ref = itx.next();
MyListener lsnr = ref.get();
if (lsnr != null)
toNotify.add(lsnr);
else
itx.remove();
}
// now iterate "toNotify" and invoke the listeners
Вы, вероятно, сходите с ума сейчас, говоря "Список! это линейная структура данных! Я не могу использовать это, вставка O (N)! "
Ну, да вы можете. Я не знаю, сколько слушателей вы планируете иметь. Но пока вы < 100 (и, скорее всего, < 100 000), стоимость линейного поиска вставки и удаления не будет иметь значения.
Гораздо интереснее с точки зрения кодирования то, как вы справляетесь со слабой ссылкой. Обратите внимание, что перед тестированием референта на нулевое значение я явно разделяю его на переменную. Это критически важный код при работе с объектами ссылки: хотя крайне маловероятно, что референт будет собираться между двумя вызовами get ()
, это возможно.
Что подводит меня к самой WeakReference
. Необходимо создать собственный подкласс, который переопределяет методы equals ()
и hashCode ()
, чтобы делегировать его референту. Я думал, что у меня просто такой класс лежит вокруг, но, видимо, нет, так что оставит это для вас, чтобы реализовать.
Вы можете продлить слабую обороту, чтобы переопределить равных и хэшкоде, то вы можете использовать их в LinkedHashSet.