Подходящий класс набора для слушателей события в Java

Похожие страницы: Java имеет структуру данных "LinkedConcurrentHashMap"?


Я ищу класс набора для содержания ссылок на слушателей события.

Идеально я хотел бы, чтобы набор имел следующие свойства (в порядке приоритета):

  1. Поддерживает порядок вставки. Более ранние слушатели могут отменить событие, добавило, препятствование тому, чтобы оно было поставлено слушателям, позже. Это повредится при использовании класса такой как HashSet чей итератор может возвратить элементы в неправильном порядке.
  2. Использование WeakReferences так, чтобы список слушателя не препятствовал тому, чтобы слушатели были собраны "мусор".
  3. Набор является a Set, таким образом, дубликаты автоматически удалены.
  4. 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. Классу нравится, это существует в библиотеке где-нибудь?

13
задан Community 23 May 2017 в 12:07
поделиться

4 ответа

Можно использовать WeakListeners (см. http://bits.netbeans.org/dev/javadoc/org-openide-util/org/openide/util/WeakListeners.html) и CopyOnWriteArraySet.

  1. Реализуйте метод remove(ListenerType listener) в источнике событий.
  2. В вашем методе register(SomeListener listener) добавьте вместо него WeakListener в коллекцию:

    listenerCollection.put((ListenerType)WeakListeners.create ((Типы слушателей). ListenerType.class, listener, this));

Когда реальный слушатель будет удален из памяти, слабый слушатель будет уведомлен, и он сам удалит регистрацию. (Поэтому для регистрации ему нужна ссылка на источник (this)). Регистрация выполняется с помощью рефлексии путем вызова метода delete из источника.

7
ответ дан 2 December 2019 в 00:18
поделиться

Вы можете обернуть каждую ссылку слушателя в слабовение , а затем используйте pophonwritearRayset .

0
ответ дан 2 December 2019 в 00:18
поделиться

Что касается ответа на вопрос, почему нужно делать принудительные покушения. Я видел случаи, когда кто-то использовал сообщение о совершении преступления, которое было неправильным или неясным. Приятно, если вы можете выполнить принудительную фиксацию, где вы можете исправить эту ошибку. Таким образом, обновленное сообщение о фиксации поступает в репозиторий, поэтому оно не теряется.

-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 () , чтобы делегировать его референту. Я думал, что у меня просто такой класс лежит вокруг, но, видимо, нет, так что оставит это для вас, чтобы реализовать.

7
ответ дан 2 December 2019 в 00:18
поделиться

Вы можете продлить слабую обороту, чтобы переопределить равных и хэшкоде, то вы можете использовать их в LinkedHashSet.

0
ответ дан 2 December 2019 в 00:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: