Проблема в том, что моя реализация слушателя создает новый массив каждый раз, когда слушатель запускается? - PullRequest
3 голосов
/ 06 мая 2011

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

Я делал что-то вроде этого:

private void notifyListeners(ObjectEvent o) {
    synchronized (this.listeners) {
        for (ObjectListener l: this.listeners)
            l.eventFired(o);
    }
}

Проблема здесь в том, что кто-то может реализовать метод eventFired, который затем оборачивается и ждет synchronize объекта, который удерживается другим потоком, который пытается добавить или удалить слушателя и ожидает на synchronized(this.listeners) строка.

Итак, я изменил метод notifyListeners таким образом:

private ObjectListener[] getObjectListeners() {
    synchronized (this.listeners) {
        return this.listeners.toArray(new ObjectListener[this.listeners.size()]);
    }
}

private void notifyListeners(ObjectEvent o) {
    ObjectListener[] listeners = this.getObjectListeners();
    for (ObjectListener l: listeners)
        l.eventFired(o);
}

Меня беспокоит влияние создания этого массива каждый раз при запуске объекта и его влияние на использование памяти приложением.

Так что я здесь, чтобы спросить, есть ли лучший способ. Возможно, я только что нашел это. Было бы достаточно легко создать ObjectListener[] каждый раз, когда я добавляю или удаляю слушателя, а затем просто выполняю итерацию без синхронизации каждый раз, когда происходит событие. Я собираюсь внести это изменение сейчас, а затем посмотреть, есть ли здесь лучшая идея.

1 Ответ

6 голосов
/ 06 мая 2011

Используйте взамен CopyOnWriteArrayList . Наблюдение заключается в том, что списки слушателей обычно проверяются гораздо чаще, чем модифицируются.

...